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-
Related
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>
I need to span some cells if next column contains "null" or ""; As on picture.
I have transposed input data, so i need to transform it before creating table.
And i dont know how to span columns in dynamic generated table.
I provide a demo-code on stackblitz;
I use angular-material package;
https://stackblitz.com/edit/angular-ivy-hknwsw?file=src%2Fapp%2Fapp.component.ts
You should just add colspan to your <td> tags and render them with ngIf when row data has information about this column. Smth like this.
https://stackblitz.com/edit/angular-ivy-evfxpi?file=src%2Fapp%2Fapp.component.ts
You can also check this thread How colSpan and row Span added to material table Header Angular 7?
Just fix your template like this
<mat-card>
<table mat-table [dataSource]="rowsInfo" class="mat-elevation-z4">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<ng-container
[matColumnDef]="column"
*ngFor="let column of columnDefs"
>
<th mat-header-cell *matHeaderCellDef>{{ column }}</th>
<ng-container
*matCellDef="let element"
>
<td
mat-cell
*ngIf="element[column] !== undefined"
[attr.colspan]="element[column].colspan"
[ngStyle]="{ 'text-align': column === 'name' ? 'left' : '' }"
>
{{ element[column].value }}
</td>
</ng-container>
</ng-container>
<tr
mat-header-row
*matHeaderRowDef="columnDefs"
></tr>
<tr mat-row *matRowDef="let row; columns: columnDefs"></tr>
</table>
</mat-card>
and the function that generates rows
public mapRows(datas: ColumnData[]): {}[] {
const result = [
{
name: {
value: "row1",
colspan: 1
}
},
{
name: {
value: "row2",
colspan: 1
}
},
{
name: {
value: "row3",
colspan: 1
}
},
];
for (let index = 0; index < datas.length; index++) {
const element = datas[index];
const propName = `prop${index}`;
const prevPropName = `prop${index - 1}`;
const hasPrevProp = index > 0;
if (element.field1 || !hasPrevProp) {
result[0][propName] = {
value: element.field1,
colspan: 1
};
} else {
result[0][prevPropName].colspan++;
}
if (element.field2 || !hasPrevProp) {
result[1][propName] = {
value: element.field2,
colspan: 1
};
} else {
result[1][prevPropName].colspan++;
}
if (element.field3 || !hasPrevProp) {
result[2][propName] = {
value: element.field3,
colspan: 1
};
} else {
result[2][prevPropName].colspan++;
}
}
return result;
}
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.
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);
})
}
I am trying to sort a table by its columns.
The problem occurs when I have to filter a result that is inside another.
I tried to access the property by bracket notation and dot notation but none gave results.
Also placing the final node in matColumnDef but it fails because there are 2 columns with the same name.
<table mat-table [dataSource]="dataSource" matSort>
<!-- Element name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<!-- Username Column -->
<ng-container matColumnDef="user.name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Username </th>
<td mat-cell *matCellDef="let element"> {{element.user.name}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
displayedColumns definition:
displayedColumns = ['name', 'user.name'];
There is a dataSource example:
[
{
id: 2,
name: "Testing",
user: {
id: 1,
name: "User Testing",
username: "test#example.com"
}
},
{
id: 4,
name: "Testing_2",
user: {
id: 3,
name: "User Testing 2",
username: "test2#example.com"
}
}
]
It was hard to find documentation on this, but it is possible by customizing the sortingDataAccessor of MatTableDataSource and a switch statement.
For example:
#ViewChild(MatSort) sort: MatSort;
ngOnInit() {
this.dataSource = new MatTableDataSource(yourData);
this.dataSource.sortingDataAccessor = (item, property) => {
switch(property) {
case 'project.name': return item.project.name;
default: return item[property];
}
};
this.dataSource.sort = sort;
}
Found here: Angular Material 2 DataTable Sorting with nested objects