How to dynamically bind angular material table with data from backend? - javascript

I am trying to bind mat-table with data from backend api based on this Angular Material Table Dynamic Columns without model. Here is the .ts file content
technologyList = [];
listTechnology = function () {
this.http.get("https://localhost:44370/api/admin").subscribe(
(result: any[]) => {
this.technologyList = result;
//creating table begins here
var displayedColumns = Object.keys(this.technologyList[0]);
var displayedRows = Object.entries(this.technologyList[0]);
this.dataSource = new MatTableDataSource(this.technologyList);
}
I am getting response from backend as technologyListwhich is
>
Array(2)
0: {id: 1, technologyName: "Python", description: "Python123", commission: "20", imageURL: "https://cutt.ly/gePgUvn", …}
1: {id: 2, technologyName: "Ruby", description: "Python123", commission: "30", imageURL: "https://cutt.ly/gePgUvn", …}
length: 2
I am trying to bind this with html using .html file as
>
<div>
<mat-table #table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container *ngFor="let disCol of displayedColumns; let colIndex = index" matColumnDef="{{disCol}}">
<mat-header-cell *matHeaderCellDef>{{disCol}}</mat-header-cell>
<mat-cell *matCellDef="let element "> {{element[disCol]}}
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
The output is a blank white block. What am I doing wrong here? Any help would be much appreciated, thank you.
Response after the proposed change
output table

Try like this:
Working Demo
displayedColumns = [];
dataSource;
listTechnology = function () {
this.http.get("https://localhost:44370/api/admin").subscribe(
(result: any[]) => {
this.technologyList = result;
this.displayedColumns = Object.keys(this.technologyList[0]);
this.dataSource = new MatTableDataSource(this.technologyList);
})
}

Related

How can i display next elements in ngfor after click in table row?

I have a nested array of objects , so i am trying to display in table row only first 3 elements in array and after i am displaying remaining elements in array as a count (i.e +2).Now if i click on remain count i need to display all the elements in array on particular row click.
I am attaching the stack blitz URL for reference :- https://stackblitz.com/edit/primeng-chip-demo-agf8ey?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts
Please help me on these issue.
Thanks in advance
try this:
<p-chip
*ngFor="let cc of slice(c); let i = index"
[label]="cc.name"
></p-chip>
in .ts file
onChip(val: any) {
this.chips[val].extand = true;
}
slice(cc: any, index: number) {
if(cc?.extand) {
return cc.values;
}
return cc.values.slice(1,3);
}
also add to every object extand: false
chips = [
{
id: 1,
values: [
{
name: 'one',
},
{
name: 'two',
},
{
name: 'three',
},
{
name: 'four',
},
{
name: 'five',
},
],
extand: false
},]
Create a template variable:
<h5>Basic</h5>
<div class="p-d-flex p-ai-center">
<table>
<tr>
<th>Id</th>
<th>Chips</th>
</tr>
<tr *ngFor="let c of chips; let val = index">
<td>{{ c.id }}</td>
<td #myCell>
<ng-container *ngIf="myCell.showAll">
<p-chip *ngFor="let cc of c.values" [label]="cc.name"></p-chip>
</ng-container>
<ng-container *ngIf="!myCell.showAll">
<p-chip
*ngFor="let cc of c.values | slice: 0:3"
[label]="cc.name"
></p-chip>
<p-chip
styleClass="chipMore"
*ngIf="c.values.length >= 3"
(click)="myCell.showAll = !myCell.showAll"
>+{{ c.values.length - 3 }}</p-chip
>
</ng-container>
</td>
</tr>
</table>
</div>
Play at edited stackblitz: https://stackblitz.com/edit/primeng-chip-demo-ykmg3t?file=src/app/app.component.html

Data binding issue in MatTableDataSource with Array of Objects in Angular

As i am trying to bind the array of objects data to a MatTableDataSource but the table shows with empty results. I guess its a minor issue with data binding. I have written the code as below.
endPointsDataSource;
endPointsLength;
endPointsPage = 0;
endPointsPageSize = 50;
allProjectsEndpointsList = [];
populateCoverage(objList) {
let tObj = { resourceName: '', endpoints: [] }
let cont = 1;
let lastName = ''
try {
lastName = objList[0][4];
} catch (e) { }
tObj.resourceName = lastName;
let resourceDefinitionList = [];
objList.forEach(function (item) {
let obj = { "projectName": item[6], "method": item[1], "endpoint": item[0], "description": item[3], "summary": item[4], "isManual": item[5] };
if (lastName == item[4]) tObj.endpoints.push(obj);
else if (lastName != item[4]) {
resourceDefinitionList.push(tObj);
tObj = { resourceName: item[4], endpoints: [obj] }; lastName = item[4]
}
});
var arr: any = []
arr = tObj;
resourceDefinitionList.push(arr)
return resourceDefinitionList;
}
showAllProjectsEndpoints() {
this.resource.getAllProjectsEndpoints().subscribe((results) => {
this.handler.hideLoader();
if (this.handler.handle(results)) {
return;
}
this.allProjectsEndpointsList = this.populateCoverage(results['data']);
this.endPointsDataSource = new MatTableDataSource(this.allProjectsEndpointsList);
}, (error) => {
this.handler.hideLoader();
this.handler.error(error);
});
}
The html template code as follows:
<div class="mat-elevation-z8 ">
<mat-table [dataSource]="endPointsDataSource">
<!-- projectName Column -->
<ng-container matColumnDef="projectName">
<mat-header-cell *matHeaderCellDef>Name
<mat-cell *matCellDef="let element">
{{element.projectName}}</mat-cell>
</mat-header-cell>
</ng-container>
<!-- method Endpoint Column -->
<ng-container matColumnDef="method">
<mat-header-cell *matHeaderCellDef>Endpoint
<mat-cell *matCellDef="let element">{{element.method}}</mat-cell>
</mat-header-cell>
</ng-container>
<!-- endpoint Column -->
<ng-container matColumnDef="endpoint">
<mat-header-cell *matHeaderCellDef>Endpoint
<mat-cell *matCellDef="let element">{{element.endpoint}}</mat-cell>
</mat-header-cell>
</ng-container>
<!-- description Column -->
<ng-container matColumnDef="description">
<mat-header-cell *matHeaderCellDef>Description
<mat-cell *matCellDef="let element">{{element.description}}</mat-cell>
</mat-header-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="endPointsColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: endPointsColumns;"></mat-row>
</mat-table>
<mat-paginator [hidden]="vulnerabilityLength == 0" matColumnDef="position"
[pageSizeOptions]="pageSizeOptions" [pageSize]="vulnerabilityPageSize"
[pageIndex]="vulnerabilityPage" (page)="changeVul($event)" [length]="vulnerabilityLength">
</mat-paginator>
</div>
Can anyone correct me what mistake i have made?
I am getting the empty table as below:
I am getting the data as below:
You need check your function populateCoverage. See that each element of your allProjectsEndpointsListarray are in the way
{resourceName:...,endpoints:[...]}
So you need write some
{{elements.endpoints[0].description}}
TIP: Sometimes is util write in a td
{{element|json}}
To see the way of the element -obviously, the table crash-

conditional css (dynamic) bason on json

The table <div class="cellSubText secondary-text {{cssSubCell}}" >{{cellData[subId]}}</div> from my table-multi-sort-cell-default.component.html using the cssClass from the tableOptions which is the cssSubCell: 'c-black fs-14px'
How we construct a conditional css based on my tableOptions cssSubCell
for example cssSubCell: 'c-black fs-14px' should only work if subId !== 'test'
I tried below, but the condition does not work or recognized , is my CSS condition structure and implementation correct?
cssSubCell: 'c-black fs-14px : subId !== "test"
#this CSS works but I want it to be condition
cssSubCell: 'c-black fs-14px'
#component A tableOptions
this.tableOptions = {
columns:[
{id:'name',name:'Deal Letter',subId:'dealType', subtitle:'Deal Type'},
{id:'annualRentCurrent',name:'Annual Rent (Current)', subId: 'annualRentProposed', subtitle:'Annual Rent (Proposed)'},
{id:'firmTermRemainingCurrent',name:'Firm Term Remaining (Current)', subId: 'proposedTerm', subtitle:'Firm Term Remaining(Proposed)'},
{id:'maxAvailableTerm',name:'Max Available Term (Current)' , subId:'proposedMaxAvailableTerm', subtitle: 'Max Available Term (Proposed)'},
{id:'cashContribution',name:'Cash Contribution'},
{id:'cashFlow',name:'Store Cash Flow'},
{id:'action', name: 'Actions', actions:[
{icon:'file_copy', name:'Copy', class:'primary-color' , },
{icon:'delete', name: 'Delete', class:'mat-error ml-7px'},
{icon:'forward', name: 'For Approval', class:'primary-color'}
]}
],
cssClass: {
cssCell:'',
cssSubCell: 'c-black fs-14px'
}
}
#table screenshot
enter image description here
#table-multi-sort-cell-default.component.html
<div class="{{cssCell}}">{{cellData[id]}}</div>
<div class="cellSubText secondary-text {{cssSubCell}}" >{{cellData[subId]}}</div>
#table-multi-sort.component.html
<ng-container *ngFor="let column of table.columns" [matColumnDef]="column.id">
<mat-header-cell class="table-multi-sort-header" *matHeaderCellDef [mat-multi-sort-header]="column.id">
<div>{{column.name}}</div>
<div class="sub-text">{{getColumnSubtitle(column.id)}}</div>
</mat-header-cell>
<mat-cell *matCellDef="let row" (click)="editRow(row)">
<ng-container *ngIf="column.id !== 'action'; then col; else actionCol"></ng-container>
<ng-template #col>
<app-table-multi-sort-cell-default [cellData]="row" [id]="column.id" [subId]="getColumnSubId(column.id)" [cssCell]="cssClass.cssCell" [cssSubCell]="cssClass.cssSubCell" ></app-table-multi-sort-cell-default>
</ng-template>
<ng-template #actionCol>
<app-table-multi-sort-cell-action [rowData]="row" [actions]="getActions(column.id)" (actionClickEvent)="clickTableAction($event,row)"></app-table-multi-sort-cell-action>
</ng-template>
</mat-cell>
</ng-container>
You need to use ngClass
<div class="cellSubText secondary-text" [ngClass]="{'c-black fs-14px' : subId !=='dealType'}">
{{cellData[subId]}}
</div>

Validate the input text user-entry inside table in angular 5

html file
<mat-table #table [dataSource]="CMDataSource">
<ng-container matColumnDef="mQues">
<mat-header-cell *matHeaderCellDef> Ticket Volume </mat-header-cell>
<mat-cell *matCellDef="let element"> <label> {{element.mQues}} </label> </mat-cell>
</ng-container>
<ng-container matColumnDef="metricUnit">
<mat-header-cell *matHeaderCellDef></mat-header-cell>
<mat-cell *matCellDef="let element">
<mat-form-field>
<input type="number" matInput (change)="userMCState(element.mQuesId, $event.target.value)">
</mat-form-field>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumnsHeaderName"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumnsHeaderName;">
</mat-row>
</mat-table>
<button mat-raised-button (click)='submitMA()'> SUBMIT </button>
component file
const CM_DATA: MetricsAssess[] = [
{ mQuesId: 1, mQues: 'English', metricUnit: 'hour' },
{ mQuesId: 2, mQues: 'French', metricUnit: 'hour' },
{ mQuesId: 3, mQues: 'Spanish', metricUnit: 'hour' },
{ mQuesId: 4, mQues: 'German', metricUnit: 'hour' }
];
CMDataSource = new MatTableDataSource(CM_DATA);
userMCState(questionNum, statusValue): void {
this.mArray.push({ "quesNum": questionNum, "userAns": statusValue});
}
submitMA(): void {
**//VALIDATE THE USER INPUT & if the ENTRY is BLANK, request the user to make entry**
let pMDataJSON = {
mAssessJSONArray: this.mArray
};
}
Here, is a set of questions displayed from table & also input text boxes.
Need to validate the User entry is NUMBER and also, if no entry is made then, request dialog box to make entry.
Kindly help me.
Please fallow thiese below steps.
remove change event because it triggers in every value changes.
try and use with ngModel
<input type="number" matInput [(ngModel)]= "element.statusValue">
do your validation in submitMA() by using loop, like below way
submitMA(): void {
let isError=false;
for(const obj of this.mArray)
{
if(!obj.statusValue || !Number.isInteger(obj.statusValue))
{
isError=true;
alert(some error occurred)
break;
}
if(isError)
{
return false
}
}
// .. possitive scenario codes
}
Note: your model class should have statusValue property.

Angular 2 Material Data Table with dynamic rows

I'm trying to add the rows of an Angular 2 Data Table ( https://material.angular.io/components/table/overview) dynamically.
I got a service ("ListService") which gives me the columns("meta.attributes") to display and i can retrieve my data from it.
The problem is, if I change the displayed columns later, after I loaded the dataSource and and the meta.attributes array gets entries (so the rows should exist in the html), it gives me this error:
Error: cdk-table: Could not find column with id "id".
Looks like the header can't find the given rows. Any ideas to fix that?
.html file:
<md-table #table [dataSource]="dataSource" mdSort>
<ng-container *ngFor="let attr of meta.attributes">
<ng-container [cdkColumnDef]="attr.name">
<md-header-cell *cdkHeaderCellDef md-sort-header>{{attr.label}}</md-header-cell>
<md-cell *cdkCellDef="let row">
{{row[attr.name]}}
</md-cell>
</ng-container>
</ng-container>
<md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
<md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
</md-table>
.ts file:
export class ListComponent implements OnInit {
displayedColumns = [];
exampleDatabase = new ExampleDatabase();
dataSource: ExampleDataSource | null;
meta: any = {
attributes: []
};
constructor(private service: ListService) {
//If i do it here it works
//this.meta.attributes.push({label: "ID", name: "id"});
}
ngOnInit() {
this.dataSource = new ExampleDataSource(this.exampleDatabase);
this.service.getMeta(this.name).subscribe(meta => {
//not here
this.meta.attributes.push({label: "ID", name: "id"});
this.service.getTableData(this.name).subscribe(data => {
this.exampleDatabase.loadData(data);
let cols = [];
for (let i = 0; i < this.meta.attributes.length; i++)
cols.push(this.meta.attributes[i].name);
this.displayedColumns = cols;
});
});
}
}
...exampleDatabase etc., same as from Angular Website
Thanks for help!
I was able to fix it by a workaround... I just added an *ngIf to the table and enable everything when service (meta) finished loading.
this.showTable = true;
console.log('table set exists');
setTimeout(() => { // necessary waiting for DOM
this.displayedColumns = ['id'];
console.log('nameCol set shown');
}, 1);
I had the same issue where it wasn't displaying. I solved it by adding an empty constructor: constructor(){} into the class or it won't set up the table properly

Categories

Resources