I want to display a list of object which have dynamic number of keys in angular inside a table, but it always shows [object,Object] in the output, I have tried multiple options from stack overflow but none of them worked. My data looks like this.
ComparableCompaniesRatiosData = [{2008: 151260,2009: 121886,2010: 122542,2011: 198630,2012: 450840,2013: 537416,2014: 673084,ComparableParty: "CompanyName",FYE: "31-12"},{2008: 151260,2009: 121886,2010: 122542,2011: 198630,2012: 450840,2013: 537416,2014: 673084,ComparableParty: "companyName",FYE: "31-12"}]
//these table headers are dynamic
ComparablePartyHeadersTrimmed = ["ComparableParty", "FYE", "2008", "2009", "2010", "2011", "2012", "2013", "2014"]
I have tried the following to display the list:
1 : I tried with classic for loop.
<tbody>
<ng-container *ngIf="showRatiosData">
<tr *ngFor="let item of [].constructor(ComparableCompaniesRatiosData.length); let item = index" data-toggle="modal">
<td *ngFor="let value of [].constructor(ComparablePartyHeadersTrimmed.length); let i = index" >
<span>{{ComparableCompaniesRatiosData[item][i]}}</span>
</td>
</tr>
</ng-container>
</tbody>
2 : with KeyValue Pipe.
<ng-container *ngIf="showRatiosData">
<tr *ngFor="let row of ComparableCompaniesRatiosData" data-toggle="modal">
<td *ngFor="let item of row | keyvalue">
<span>{{item.value}}</span>
</td>
</tr>
</ng-container>
3 : And with simple angular *ngFor as well.
<ng-container *ngIf="showRatiosData">
<tr *ngFor="let item of ComparableCompaniesRatiosData" data-toggle="modal">
<td *ngFor="let row of ComparablePartyHeadersTrimmed" >
<span>{{item[row]}}</span>
</td>
</tr>
</ng-container>
Ok, I've added a new method getValue() which takes the item and property name and returns the value.
getValue(item, property): any {
return item[property];
}
Then in the HTML, first loop through the data, then through the headers, and call the getValue() with the row and the header name.
<table class="table" >
<thead>
<tr>
<th *ngFor="let header of ComparablePartyHeadersTrimmed" >{{header}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of ComparableCompaniesRatiosData">
<td *ngFor="let property of ComparablePartyHeadersTrimmed" >
{{getValue(item,property)}}
</td>
</tr>
</tbody>
</table>
Working example: https://stackblitz.com/edit/angular-dynamic-table-columns-example
Related
I have a table built in Angular 8. I am not using Material UI.
I want to reorder the columns in the table using JSON. Is there any way that could be done?
My Angular table code is like below:
<table>
<thead class="thead-light">
<tr>
<th *ngFor="let data of tableHeaders">
{{ data.value }}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of transactions ">
<td>{{ data.firstName }}</td>
<td>{{ data.regNo }}</td>
<td>{{ data.course }}</td>
</tr>
</tbody>
</table>
My tableheader json:
this.tableHeaders = [
{
"id": 'first_name',
"value":"Name",
},
{
"id": 'reg_no',
"value":"Reg No"
},
{
"id": 'course_name',
"value":"Course"
},
]
While I am able to change the order of the table headers by setting an id and sorting the array - tableHeaders, but how do I do the same for the td?
Any help would be appreciated.
You need to modify header and content's key to make it relate together something like
Full example: Stackblitz
.ts
this.tableHeaders = [
{
"id": 'first_name',
"value":"Name",
"key": "firstName"
},
{
"id": 'reg_no',
"value":"Reg No",
"key":"regNo"
},
{
"id": 'course_name',
"value":"Course",
"key": "course"
},
]
.html
<table>
<thead class="thead-light">
<tr>
<th *ngFor="let data of tableHeaders">
{{ data.value }}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of transactions">
<td *ngFor="let header of tableHeaders">
{{ data[header.key] }}
</td>
</tr>
</tbody>
</table>
I have a string of array and I want to display that array in first column of the table like this
c1 c2 c3 c4 c5 c6
d1 - - - - -
d2 - - - - -
d3 - - - - -
d4 - - - - -
the string of array is like this
data: string[] = ['d1', 'd2', 'd3', 'd4',];
so here is my html code
<p-table [columns]="panel.headers" [value]="panel.data">
<ng-template pTemplate="header" let-columns>
<tr *ngFor="let headerRow of panel.headers">
<th *ngFor="let col of headerRow.cols" [attr.colspan]="col.colspan"
[attr.rowspan]="col.rowspan">
{{col.label}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-row>
<tr>
<td *ngFor="let col of panel.headers[panel.headers.length-1].cols"
class="{{row[col.dataClasses]}}">
{{row[col.valueField]}}
</td>
</tr>
</ng-template>
</p-table>
See the stackblitz https://stackblitz.com/edit/primeng-tabledynamic-demo-h58rsj
in this example, I want to print tiers in the first column.
please help to solve this..
Thanks
Just add the column at the beginning:
<ng-template pTemplate="body" let-row>
<tr>
<td>my array goes here</td>
<td *ngFor="let col of panel.headers[panel.headers.length-1].cols"
class="{{row[col.dataClasses]}}">
{{row[col.valueField]}}
</td>
</tr>
</ng-template>
And in your header:
<ng-template pTemplate="header" let-columns>
<tr *ngFor="let headerRow of panel.headers">
<th></th>
<th *ngFor="let col of headerRow.cols" [attr.colspan]="col.colspan"
[attr.rowspan]="col.rowspan">
{{col.label}}
</th>
</tr>
</ng-template>
I have a nested HTML table which expands on click. When I click inner row, I would like to get column value. Right now, I am getting the column value on click of outer row.
For instance in the below image, when I click coding/testing, I would like to pass an alert as "Place". Right now, I get alert as "place" when I click city.
Component:
trigger(){
var table: any = document.getElementById("table");
var rows = table.rows;
for (var i = 0; i < rows.length; i++) {
rows[i].onclick = (function (e) {
var j = 0;
var td = e.target;
while( (td = td.previousElementSibling) != null )
j++;
alert(rows[0].cells[j].innerHTML);
});
}
}
Demo
I'm not sure why you have this code in your trigger function. But, if you need to get the column name when a data cell is clicked, you can use the following approach.
Inject into your trigger function call a current event object and your header row element template variable:
<table class="table table-hover table-bordered table-responsive-xl" id="table">
<tr #header>
</tr>
<tbody>
<ng-container *ngFor="let data of data1">
<ng-container *ngIf="data.expanded">
<tr *ngFor="let data of findDetails(data)" (click)="trigger($event, header)">
</tr>
</ng-container>
</ng-container>
</tbody>
</table>
So, #header name is assigned to the first tr element and then it's passed along with $event to the trigger function.
In your trigger function, consume these two parameters. $event will be a regular MouseEvent object and header will be a regular tr element. After this, you can find the clicked column header by the clicked cell index in your row. gsnedders in the StackOverflow thread provided a solution for how to find the element index inside its parent. Your trigger function may look like:
trigger($event, header) {
const index = this.getChildNumber($event.target);
alert(header.childNodes[index].textContent.trim());
}
This StackBlitz project illustrates this approach.
You don't need any DOM manipulation, you can simplify your solution as below:
app.component.ts
// .......
export class AppComponent {
trigger(columnName: string) {
alert(columnName);
}
// .......
}
app.component.html
<table class="table table-hover table-bordered table-responsive-xl" id="table">
<tr>
<td> Name </td>
<td> Place </td>
<td> Phone </td>
</tr>
<tbody>
<ng-container *ngFor="let data of data1">
<tr (click)="data.expanded = !data.expanded">
<td (click)="trigger('Name outer')"> {{ data.expanded ? '–' : '+'}} {{data.name}} </td>
<td (click)="trigger('Place outer')"> {{data.place}} </td>
<td (click)="trigger('Phone outer')"> {{data.phone}} </td>
<td (click)="trigger('Hobbies Outer')"> {{data.hobbies}} </td>
<td (click)="trigger('Profession outer')"> {{data.profession}} </td>
</tr>
<ng-container *ngIf="data.expanded">
<tr *ngFor="let data of findDetails(data)">
<td style="padding-left: 12px" (click)="trigger('Name inner')"> {{data.datades.name}} </td>
<td (click)="trigger('Hobbies inner')"> {{data.datades.hobbies}} </td>
<td (click)="trigger('Profession inner')"> {{data.datades.profession}} </td>
</tr>
</ng-container>
</ng-container>
</tbody>
</table>
I have a simple Angular.js application that grabs tabular data from a mysql database and shows it in a simple bootstrap table. I’m using this code below to show the table column names without hardcoding them individually…
HTML:
<table class="table">
<thead>
<tr style="background:lightgrey">
<th ng-repeat="column in columns"> {{ column }} </th>
</tr>
</thead>
and in the controller I create ’$scope.columns’ with something like this…
var columnNames = function(dat) {
var columns = Object.keys(dat[0]).filter(function(key) {
if (dat[0].hasOwnProperty(key) && typeof key == 'string') {
return key;
}
});
return columns;
};
DataFactory.getTables(function(data) {
$scope.columns = columnNames(data);
$scope.tables = data;
});
And this works as expected and it’s great, but what about the the rest of the data.. So for example, the body of my table currently looks like this…
HTML:
<tbody>
<tr ng-repeat="x in tables ">
<td> {{ x.id}} </td>
<td> {{ x.name }} </td>
<td> {{ x.email }} </td>
<td> {{ x.company }} </td>
</tbody>
I’ve tried using two loops like this…
HTML:
<tbody>
<tr ng-repeat="x in tables">
<td ng-repeat=“column in columns”> {{ x.column }} </td>
</tr>
</tbody>
But this code doesn’t work, So is it possible to populate a table with angular without hardcoding the column names in HTML, and if so whats the most efficient way to do so?
You might want to try this https://jsfiddle.net/8w2sbs6L/.
<div data-ng-app="APP">
<table ng-controller="myController" border=1>
<thead>
<tr>
<td ng-repeat="column in columns">{{column}}</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in tables">
<td ng-repeat="column in columns">{{x[column]}}</td>
</tr>
</tbody>
</table>
</div>
<script>
'use strict';
angular.module('APP', [])
.controller('myController', ['$scope', function($scope){
$scope.tables = [
{
"column1":"row1-column1",
"column2":"row1-column2",
"column3":"row1-column3",
"column4":"row1-column4"
},
{
"column1":"row2-column1",
"column2":"row2-column2",
"column3":"row2-column3",
"column4":"row2-column4"
}
];
$scope.columns = [
"column1",
"column2",
"column3",
"column4"
];
}]);
</script>
I have a list of items of different types and I would like to display them in a table.
The items of one type will have two columns and items of another type just one. Any suggestions how to change conditionally the colspan on the <> tag on fly?
<div ng-init="items = [
{name:'item1', old:1, new:2},
{name:'item2', old:2, new:2},
{name:'item3', msg: 'message'},
{name:'item4', old:0, new:2}
]">
<table border=1>
<tr ng-repeat="item in items" >
<th>{{item.name}}</th>
<td>{{item.old}}</td>
<td colspan='2'>{{item.msg}}</td>
<td>{{item.new}}</td>
</tr>
</table>
Here is the example to play in jsfiddle: http://jsfiddle.net/38LXt/1/
Thanks!
You can use conditional directives, such as ng-show, to do something like this:
<table border=1>
<tr ng-repeat="item in items" >
<th>{{item.name}}</th>
<td>{{item.old}}</td>
<td colspan="2" ng-show="item.type == 'typeA'">{{item.msg}}</td>
<td ng-show="item.type == 'typeB'">{{item.msgB1}}</td>
<td ng-show="item.type == 'typeB'">{{item.msgB2}}</td>
<td>{{item.new}}</td>
</tr>
</table>
More info about ng-show:
ngShow directive