How to display 2 arrays in 1 table using angular? - html

I want to create the same table as the image. And, I need to add data from two arrays with the first two separators as a veg-topping and the second az non-veg-topping under the non-plant table header.
My list is:
this.vegtooping = [
{vegproduct: 'Tomatoes($1.00)', cost :1 ,small:false, medium: false, larg: false, xlarg: false},
{vegproduct: 'Onions($0.50)',cost :0.5, small:false, medium: false, larg: false, xlarg: false},
];
this.nonvegtooping = [
{nonvegproduct: 'Sausage ($1.00)', cost :1 ,small:false, medium: false, larg: false, xlarg: false},
];
<p-table [value]="vegtooping" [value]="vegtooping" [tableStyle]="{'min-width': '50rem'}">
<ng-template pTemplate="header">
<tr>
<th rowspan="2">Toppings</th>
<th colspan="4">Pizza Size</th>
</tr>
<tr>
<th>Small($5)</th>
<th>Medium($7)</th>
<th>Larg($8)</th>
<th>Xxtra Larg($9)</th>
</tr>
<tr>
<th colspan="5">
veg Toppings
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-vegtooping let-nonvegtooping>
<tr>
<td>{{nonvegtooping.vegproduct}}</td>
<td> <p-checkbox >{{nonvegtooping.Small}}</p-checkbox></td>
<td><p-checkbox>{{nonvegtooping.Medium}}</p-checkbox></td>
<td> <p-checkbox>{{nonvegtooping.aa }}</p-checkbox></td>
<td> <p-checkbox>{{nonvegtooping.ss }}</p-checkbox></td>
</tr>
<!-- <td >{{vegtooping.vegproduct}}</td>
<td> <p-checkbox >{{vegtooping.Small}}</p-checkbox></td>
<td><p-checkbox>{{vegtooping.Medium}}</p-checkbox></td>
<td> <p-checkbox>{{vegtooping.lastYearProfit | currency: 'USD'}}</p-checkbox></td>
<td> <p-checkbox>{{vegtooping.thisYearProfit | currency: 'USD'}}</p-checkbox></td>
-->
</ng-template>

Related

How to combine two arrays into one array of objects?

Can I use an ngFor instead of repeating <table> two times?
NB: I thought to combine all the items into objects as items of a single array of mapping(each object contains a variable, label and value) but it does not work for me)
....
this.maxValueTable.push(selectedData.res.maxValue);
this.minValueTable.push(selectedData.res.minValue);
...
<div style="display: flex;">
<table style="width:100%;">
<thead>
<tr>
<th>Max</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let maxValue of maxValueTable">
<td> {{ maxValue | numberFormatter: (getUnit() | async)}}</td>
</tr>
</tbody>
</table>
<table style="width:100%;">
<thead>
<tr>
<th>Min</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let maxValue of minValueTable">
<td> {{ MinValue| numberFormatter: (getUnit() | async)}}</td>
</tr>
</tbody>
</table>
</div>
Another way:
<!--create an array directly in the .html: you can also use
a variable in your .ts-->
<table *ngFor="let table of [{head:'Max',data:maxValueTable},
{head:'Max',data:maxValueTable}]
style="width:100%;">
<thead>
<tr>
<!--use table.head-->
<th>{{table.head}}</th>
</tr>
</thead>
<tbody>
<!--see how iterate over table.data-->
<tr *ngFor="let maxValue of table.data">
<td> {{ maxValue | numberFormatter: (getUnit() | async)}}</td>
</tr>
</tbody>
</table>
If your arrays has the same length and only want a table, iterate over one array ans use the index to get the value of the another one
<table style="width:100%;">
<thead>
<tr>
<th>Max</th>
<th>Min</th>
</tr>
</thead>
<tbody>
<!--see the "let i=index"-->
<tr *ngFor="let maxValue of maxValueTable;let i=index">
<td> {{ maxValue | numberFormatter: (getUnit() | async)}}</td>
<!--use the "index" "i" to get the element of the another array-->
<td>
{{ minValueTable[i] | numberFormatter: (getUnit() | async)}}
</td>
</tr>
</tbody>
</table>
in this case you can also use map to create a new Array
minMax=this.minValueTable.map((x,index)=>({
min:x,
max:this.maxValueTable[index]
}))
And use {{value.min}} and {{value.max}}
You can create a function that will combine min and max values into an array like that:
mergeIntoArray(maxValue: Array<number>, minValue: Array<number>): IMergedObj[] {
let mergedArray = [];
maxValue.forEach((value, index) => {
let tempObj = {};
tempObj['maxValue'] = value;
tempObj['minValue'] = minValue[index];
mergedArray.push(tempObj);
});
return mergedArray;
}
and call this function like that:
let minAndMax = [];
this.minAndMax = this.mergeIntoArray(this.maxValueTable, this.minValueTable);
after that, use this variable (minAndMax) in your HTML template. This way you do not need to use ngFor twice.
<table style="width:100%;">
<thead>
<tr>
<th>Max</th>
<th>Min</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of minAndMax">
<td>{{ item.maxValue }}</td>
<td>{{ item.minValue }}</td>
</tr>
</tbody>
</table>
Here is the stackblitz link created for you. Hope that might help you.
You can use *ngTemplateOutlet for this case:
<div style="display: flex;">
<ng-container *ngTemplateOutlet="tableTemplate; context: {$implicit: maxValueTable, header: 'Max'}"></ng-container>
<ng-container *ngTemplateOutlet="tableTemplate; context: {$implicit: minValueTable, header: 'Min'}"></ng-container>
</div>
<ng-template #tableTemplate let-values, let-header="header">
<table style="width:100%;">
<thead>
<tr>
<th>{{ header }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let value of values">
<td> {{ value | numberFormatter: (getUnit() | async) }}</td>
</tr>
</tbody>
</table>
</ng-template>
And you will get the same table rendered twice - for Max and Min values.
As you can see, the arguments are passed as a second argument inside ngTemplateOutlet:
context: {$implicit: valuesArgument, header: headerArgument}
Later you could use this template to create infinite amount of tables:
<div *ngFor="let table of tables">
<ng-container *ngTemplateOutlet="tableTemplate; context: {$implicit: table.values, header: table.header}"></ng-container>
</div>
Assuming your tables property will look like
export class C {
tables: Table[] = [{header: 'Min', values: [1, 2, 3]}, {header: 'Max', values: [4, 5, 6]}, {header: 'Other', values: [0, -1, -2]}]
}

How to display object of array data on html table in Angular

I need to display below object of array in html table like that image. My data array like this.
data = [{id: 0 , name: 'one' , tags: ['a' , 'b' , 'c']} , {id: 1 , name: 'two', tags: ['r' , 't' , 'y']} , {id: 2 , name: 'three' , tags: ['a' , 'b' , 'c']} , {id: 3 , name: 'four' , tags: ['a' , 'b' , 'c']}]; .
So i tried like this but it's not working as expect on image.
<table class="table table-hover table-bordered">
<thead>
<tr>
<th scope="col">Tag Type</th>
<th scope="col">Tags</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let tag of data; let i = index">
<td>{{ tag.id }}</td>
<table class="table">
<tr *ngFor="let el of tag.tags">
<td>{{el}}</td>
</tr>
</table>
<td>
<div align="center">
<a matTooltip="edit tag"><i>mode_edit</i></a>
</div>
</td>
</tr>
</tbody>
</table>
this is the result i got.Any idea how to do this?
I have made a few modifications into the code.
Instead of creating a new nested table,I have tried create separate rows in the main table. I have hid the TagType And Action, where it is not to be displayed based on the index.
For the striped pattern, I have added "table-striped" class to the table.
The Html code would look like this
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
<th scope="col">Tag Type</th>
<th scope="col">Tags</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let tag of data; let i = index">
<tr *ngFor="let el of tag.tags; let i2=index">
<td *ngIf="i2==0"> {{tag.id}} </td>
<td *ngIf="i2!=0"> </td>
<td> {{el}} </td>
<td>
<div align="center">
<a matTooltip="edit tag"><i>mode_edit</i></a>
</div>
</td>
</tr>
</ng-container>
</tbody>
</table>
StackBlitz working demo: https://stackblitz.com/edit/angular-ivy-aqmrzy

Need to reload many times to see correctly angular html component

I'm using a template in my project. Before loging the page is configured to redirect in to a /threads all the methods that use is calling but is not showing in the page.
I need to refresh at least 3 times to show it correctly.
And the console error
On my component.ts:
ngOnInit(): void {
this.filters = {
id: '',
title: '',
description: '',
category: '',
initialDate: '',
finalDate: '',
status: 'Abierto',
user: ''
}
this.term = '';
// Get threads by filter
this.getThreads(this.filters);
}
// Get
private getThreads(filters: any) {
this.threadService.getByFilters(filters).subscribe(threads => {
this.threads = this.filteredThreads = threads;
this.threads.forEach(thread => thread.isSelected = false);
});
}
on my component.html
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th scope="col" *ngFor="let header of headers" (click)="setSortingOptions(header)">
<span class="sortable" *ngIf="header.toLowerCase() === this.sortHeader">
<i
[ngClass]="this.isFlowReverse ? 'ti-arrow-circle-down' : 'ti-arrow-circle-up'"></i>
</span>
<span class="sortable">
{{header}}
</span>
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let thread of filteredThreads | orderBy: this.sortHeader : this.isFlowReverse: true | slice: (page-1) * pageSize : page * pageSize"
(click)="preview(thread)" [ngClass]="thread.isSelected ? 'selected': '' ">
<td>
<ngb-highlight [result]="thread.status" [term]="term"></ngb-highlight>
</td>
<td>
<ngb-highlight [result]="thread.title" [term]="term"></ngb-highlight>
</td>
<td>
<ngb-highlight [result]="thread.category" [term]="term"></ngb-highlight>
</td>
<td>
<ngb-highlight [result]="thread.date" [term]="term"></ngb-highlight>
</td>
<td>
<ngb-highlight [result]="thread.user" [term]="term"></ngb-highlight>
</td>
</tr>
</tbody>
</table>
</div>

angular render table ngFor for nested json with dynamic column names

Still learning Angular (version 8). I have the following JSON
{layer1 : [
{
id: 'lay1',
name: 'first layer',
results:
[
{ rows: [{ col1: '0', description: 'any'}, {col1: '0b', description: 'meh'}] },
{ rows: [{ col1: '1', description: 'some'}] },
]
}
]
, layer2: [
{
id: 'lay2',
name: 'second layer'
results:
[
{ rows: [{ col1: '7', description: 'more'}] },
{ rows: [{ col1: '8', description: 'none'}] },
]
}
]
}
The result should be a table like this
<table id='lay1'>
<tr>
<td>0 </td>
<td>any</td>
</td>
<tr>
<td>0b </td>
<td>meh</td>
</td>
<tr>
<td>1</td>
<td>some</td>
</td>
</table>
<table id='lay2'>
<tr>
<td>7 </td>
<td>more</td>
</td>
<tr>
<td>8</td>
<td>none</td>
</td>
</table>
note: results rows columns can change (sometimes 2 columns, sometimes 4 columns) and change the names (could be 'col1' but could be 'ident' or any other name). I have tried several options but I'm stuck on this. Any help highly appreciated
Try this -
<table *ngFor='let tableItem of data | keyvalue' [id]='tableItem?.value[0]?.id'>
<tbody *ngFor='let rowsItem of tableItem?.value[0]?.results; let rowIndex = index'>
<tr *ngFor='let rowItem of rowsItem?.rows; let rowIndex = index'>
<td *ngFor='let colItem of rowItem | keyvalue; let colIndex = index'>
{{colItem?.value}}
</td>
</tr>
</tbody>
</table>
Working Example

Unable to display NO DATA message when data does not exist in the table

I am displaying table data using NgTableParams in angularjs. I was trying to show NO DATA EXISTS in the table when the data is not available or length is zero, but my code doesn't seems to work.
Demo : http://plnkr.co/edit/nEbjQE1NQW7VF8dlZvyy?p=preview
sample code:
<table ng-table="tableParams" class="table" show-filter="true">
<tbody ng-repeat="user in $data">
<tr ng-show="$data.length > 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
{{user.name}}</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
{{user.age}}</td>
</tr>
<tr ng-show="$data.length === 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
NO DATA FOUND</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
</td>
</tr>
</tbody>
js code:
app.controller('MainCtrl', function($scope, NgTableParams) {
$scope.data1 = [];
console.log(" $scope.data1 length " + $scope.data1.length);
$scope.tableParams = new NgTableParams({}, { dataset: $scope.data1});
});
Tried as below too , but it is not displaying the table header and filter for the columns..
Demo : http://plnkr.co/edit/XAOO5tPALVOkQW9hhJCs?p=preview:
<tbody ng-show="!$data.length">
<tr>
<td>
NO DATA FOUND
</td>
</tr>
</tbody>
<tbody ng-repeat="user in $data">
<tr ng-show="$data.length > 0">
....
</tbody>
There are two issues here
The first one is that your ng-repeat directive is in your tbody this will cause your table body to be rendered for every single element in your array.
The second one is that your "NO DATA FOUND" message is inside of your ng-repeat block, no element will be rendered if $data is empty.
The solution would be to move the ng-repeat from your tbody to the actual element that you want to repeat for every item in your array, in this case, the tr that contains the data to be displayed.
<table ng-table="tableParams" class="table" show-filter="true">
<tbody>
<tr ng-repeat="user in $data" ng-show="$data.length > 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
{{user.name}}</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
{{user.age}}</td>
</tr>
<tr ng-show="$data.length === 0">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
NO DATA FOUND</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'"></td>
</tr>
</tbody>
</table>
Hope it helps!