I am trying to sort a mat-table using the mat-sort-header. I am able to do it with common attributes like string or number.
<table #tablaClientes mat-table [dataSource]="dataSource" matSort multiTemplateDataRows>
<!-- Id Column -->
<ng-container matColumnDef="idIngreso">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Id Comprobante</th>
<td mat-cell *matCellDef="let row">{{row.idIngreso}}</td>
</ng-container>
<!-- Proveedor Column -->
<ng-container matColumnDef="idProveedor">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Nombre Proveedor</th>
<td mat-cell *matCellDef="let row">{{row.idProveedor.nombre}}</td>
</ng-container>
<!-- Fecha Compra Column -->
<ng-container matColumnDef="fechaCompra">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Fecha de Compra</th>
<td mat-cell *matCellDef="let row">{{row.fechaCompra}}</td>
</ng-container>
<!-- Fecha Recepcion Column -->
<ng-container matColumnDef="fechaRecepcion">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Fecha de Recepcion</th>
<td mat-cell *matCellDef="let row">{{row.fechaRecepcion}}</td>
</ng-container>
<!-- Monto Total Column -->
<ng-container matColumnDef="totalIngreso">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Monto Total</th>
<td mat-cell *matCellDef="let row">{{row.totalIngreso |currency}}</td>
</ng-container>
However I can't sort by idProveedor since it's an object.
Thank you very much!
The easer way is add to your dataSource a new property and sort by this new property like this SO (really if you don't need the "idProveedor" object, your dataSource can be transform to some like
this.data.forEach(x=>{
x.proveedorNombre=x.idProveedor.nombre
delete x.idProveedor
}
Another solution is create a sortingDataAccesor
this.dataSource.sortingDataAccessor = (item, property) => {
if (property=="idProveedor")
return item.nombre;
if (property=="idIngreso")
return item.idIngreso
if (property=="fechaCompra")
return item.fechaCompra
...
}
An example simple in this stackblitz
Related
I have stored some data in db.json. In the ts file I have used the get function and received it in a variable. The data is coming through successfully( I checked using console.log). However it is not displaying in the html table i have created.
Below is my html file
<p>people works!</p>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Position Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element; let i = index"> {{i+1}} </td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="company">
<th mat-header-cell *matHeaderCellDef> Comapnay </th>
<td mat-cell *matCellDef="let element"> {{element.company}} </td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef> Email </th>
<td mat-cell *matCellDef="let element"> {{element.email}} </td>
</ng-container>
<ng-container matColumnDef="address">
<th mat-header-cell *matHeaderCellDef> Address </th>
<td mat-cell *matCellDef="let element"> {{element.address}} </td>
</ng-container>
<ng-container matColumnDef="active">
<th mat-header-cell *matHeaderCellDef> Active </th>
<td mat-cell *matCellDef="let element"> {{element.active}} </td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef> Action </th>
<td mat-cell *matCellDef="let element; let j = index"><button (click) = "detail(j)"> {{element.action}} </button></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<div id = "Detail">
{{userDetail.id}}<br>
{{userDetail.name}}<br>
{{userDetail.company}}<br>
{{userDetail.email}}<br>
{{userDetail.active}}<br>
{{userDetail.action}}
</div>
And the next code is my ts file
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { user } from './userInterface';
#Component({
selector: 'app-people',
templateUrl: './people.component.html',
styleUrls: ['./people.component.css']
})
export class PeopleComponent implements OnInit {
displayedColumns=["id","name","company","email","address","active","action"];
UserDb:user[]=[];
dataSource = this.UserDb;
userDetail: user={
id: 0,
name: '',
company: '',
email: '',
address: '',
active: false,
action: ''
};
detail(rowid: number) {
this.userDetail = this.UserDb[rowid];
}
constructor(private _http: HttpClient) {
}
ngOnInit(): void {
console.log("im working");
this._http.get("http://localhost:3002/posts").subscribe((users:any)=>{
this.UserDb = users;
console.log(this.UserDb);
})
}
}
`
My entire data is being shown in the console.
data in the console. But not showing under the table
It looks that dataSource gets the value of UserDB before UserDB is populated. So, you get valid data in the console; but not in HTML. Why do you use two variables in the first place?
Hi I found the error in the code. Actually, the variables used in json needs to be exactly the same to the one used in the front-end part of the program.Like in my ts code i have used 'id' and 'name'.But in json the same variables I've written as 'Id' and 'Name'. Hence, the problem.
I have a variable in my ts that contains a value of 3 (array length), I want to use it in my html to increment the value of index ([0]) until the value of 3 is reached.
<table mat-table [dataSource]="dataSourceQuizOverview" matSort>
<ng-container matColumnDef="question_text">
<th class="font" mat-header-cell *matHeaderCellDef mat-sort-header>Questions</th>
<td class="font" mat-cell *matCellDef="let row">{{row.quiz_records[0].question_text}}</td>
</ng-container>
<ng-container matColumnDef="user_answers">
<th class="font" mat-header-cell *matHeaderCellDef mat-sort-header>Answer</th>
<td class="font" mat-cell *matCellDef="let row">{{row.quiz_records[0].user_answers}}</td>
</ng-container>
</table>
ts
quiz_recordsLength.length: number = 3;
You should check, NgForOf Directive. This should solve your issue.
Also, for future questions, please remember this: How much research effort is expected of stack overflow. Posting a new question should be your last resort.
I have an angular material table
(HTML)
<table mat-table
[dataSource]="dataSource" multiTemplateDataRows
class="mat-elevation-z8">
<ng-container *ngIf="{{column}}" matColumnDef="{{column}}" *ngFor="let column of displayedColumns">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element"> {{element[column]}} </td>
</ng-container>
I want to change the styling on the element if it equals 'Missing' (e.g. {{element[column}} == Missing then change styling).
(style) (HTML)
<mat-chip *ngIf="element.status=='Missing'" style="background-color: #ec9d9d; color: red">Missing</mat-chip>
How can I do this in the HTML? I only want to do this if the displayedColumn 'status' is equal to 'Missing'.
(Typescript)
displayedColumns: string[] = [
'id',
'tradingPartnerTradingPartner',
'fileFormatFileFormat',
'status',
];
you could use the ng-class directive
in your example, using it should be something like this:
(Assuming the mat-chip would get placed into this cell I modified below)
<table mat-table [dataSource]="dataSource" multiTemplateDataRows
class="mat-elevation-z8">
<ng-container *ngIf="{{column}}" matColumnDef="{{column}}" *ngFor="let column of displayedColumns">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element"
[ngClass]="{missing: element.status=='Missing' }"> {{element[column]}} </td>
</ng-container>
...
and don't forget to create the css for the .missing class we are referencing in the ngClass directive:
.missing {
background-color: #ec9d9d;
color: red
}
I have a Nested JSON and I want to output it to Mat-Table... Can you guys help me with this, please?
I can output the json susa, how do I output mandantKagAccountEntity?
My code:
// Nested JSON
{
"success": true,
"susa": [
{
"accountlinevaluesId": 1,
"accountlineId": 1,
"mandantKagId": 660,
"mandantAccountsId": 1,
"period": "7",
"accountNumber": 27,
"name": "EDV-Hardware/Software",
"amount": 55.16859,
"mandantKagAccountEntity": {
"mandantKagId": 660,
"mandantId": 1,
"kagNumber": 2000,
"kagText": "A. I. 1. EDV-Software"
}
},
] }
// test.component.ts
private loadData() {
const yearString = this.year ? `${this.year}` : `${new Date().getFullYear()}`;
this.balanceListService.getDataForAllMonth(yearString).subscribe(
(resp: any) => {
const data = resp.success ? resp.susa : null;
if (null !== data && data) {
.... }
}
}
It depends what exactly you want to pass to mat-table.
If it's an array of the nested property mandantKagAccountEntity, then this should do the trick:
const data = resp.success ? resp.susa.map((item) => item.mandantKagAccountEntity) : null;
If you only want the very first occurrence of mandantKagAccountEntity, then you don't have to iterate over the entire nested object:
const data = resp.success ? resp.susa[0]?.mandantKagAccountEntity : null;
// EDIT: OP had a misleading question. He actually wants to display the entire data, including the nested object. Here's the answer to that:
displayedColumns is being used by mat-table to define which columns to show. You can edit the names to your liking.
displayedColumns: string[] = [
'accountlinevaluesId',
'accountlineId',
'mandantKagId',
'mandantAccountsId',
'period',
'accountNumber',
'name',
'amount',
'mandantKagAccountEntity-mandantKagId',
'mandantKagAccountEntity-mandantId',
'mandantKagAccountEntity-kagNumber',
'mandantKagAccountEntity-kagText',
];
Each column needs a container inside the mat-table that defines how to display the property:
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!--- 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="accountlinevaluesId">
<th mat-header-cell *matHeaderCellDef> accountlinevaluesId</th>
<td mat-cell *matCellDef="let element"> {{element.accountlinevaluesId}}</td>
</ng-container>
<ng-container matColumnDef="accountlineId">
<th mat-header-cell *matHeaderCellDef> accountlineId</th>
<td mat-cell *matCellDef="let element"> {{element.accountlineId}}</td>
</ng-container>
<ng-container matColumnDef="mandantKagId">
<th mat-header-cell *matHeaderCellDef> mandantKagId</th>
<td mat-cell *matCellDef="let element"> {{element.mandantKagId}}</td>
</ng-container>
<ng-container matColumnDef="mandantAccountsId">
<th mat-header-cell *matHeaderCellDef> mandantAccountsId</th>
<td mat-cell *matCellDef="let element"> {{element.mandantAccountsId}}</td>
</ng-container>
<ng-container matColumnDef="period">
<th mat-header-cell *matHeaderCellDef> period</th>
<td mat-cell *matCellDef="let element"> {{element.period}}</td>
</ng-container>
<ng-container matColumnDef="accountNumber">
<th mat-header-cell *matHeaderCellDef> accountNumber</th>
<td mat-cell *matCellDef="let element"> {{element.accountNumber}}</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> name</th>
<td mat-cell *matCellDef="let element"> {{element.name}}</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> amount</th>
<td mat-cell *matCellDef="let element"> {{element.amount}}</td>
</ng-container>
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef> position</th>
<td mat-cell *matCellDef="let element"> {{element.position}}</td>
</ng-container>
<ng-container matColumnDef="mandantKagAccountEntity-mandantKagId">
<th mat-header-cell *matHeaderCellDef> mandantKagAccountEntity-mandantKagId</th>
<td mat-cell *matCellDef="let element"> {{element.mandantKagAccountEntity.mandantKagId}}</td>
</ng-container>
<ng-container matColumnDef="mandantKagAccountEntity-mandantId">
<th mat-header-cell *matHeaderCellDef> mandantKagAccountEntity-mandantId</th>
<td mat-cell *matCellDef="let element"> {{element.mandantKagAccountEntity.mandantId}}</td>
</ng-container>
<ng-container matColumnDef="mandantKagAccountEntity-kagNumber">
<th mat-header-cell *matHeaderCellDef> mandantKagAccountEntity-kagNumber</th>
<td mat-cell *matCellDef="let element"> {{element.mandantKagAccountEntity.kagNumber}}</td>
</ng-container>
<ng-container matColumnDef="mandantKagAccountEntity-kagText">
<th mat-header-cell *matHeaderCellDef> mandantKagAccountEntity-kagText</th>
<td mat-cell *matCellDef="let element"> {{element.mandantKagAccountEntity.kagText}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
Considering you do want to show all data, there's no further mapping of the response needed, other than
this.dataSource = resp.success ? resp.susa : null;
I have solved the problem. Again for your understanding :) The code outputs the whole JSON object (including nesting). Hope I can help those of you who have the exact same problem I had.
// Fill the table with data
private loadData() {
this.balanceListService.getDataForAllMonth(yearString).subscribe(
(resp: any) => {
let data = resp.susa;
if (null !== data && data) {
data = data.map((item) => {
const kag = item.mandantKagAccountEntity;
delete item.mandantKagAccountEntity;
return { ...item, ...kag }; // merge two objects into one
});
}
});
}
I've followed the Angular docs here https://angular.io/api/common/NgIf to create an NgIf else conditional over my Material Table. It is reading remote JSON file as API.
The API is twitter data and one of the fields I want to run condition on is 'replies'. If there are no replies, I want to replace the "0" with a "-".
I am getting the error
Can't have multiple template bindings on one element. Use only one attribute prefixed with * (" Replies
]*ngIf="hashtags.replies<1; else noReplies"> {{hashtags.replies}}
"):`
So it seems I cannot run NgIf and interpolate my data in the same element, I've tried all kinds of combinations in the HTML but I am real stuck.
HTML
<ng-container matColumnDef="replies">
<th mat-header-cell *matHeaderCellDef> Replies </th>
<td mat-cell *matCellDef="let hashtags" *ngIf="hashtags.replies<1; else noReplies"> {{hashtags.replies}} </td>
<ng-template #noReplies>-</ng-template>
</ng-container>
Try
<ng-container matColumnDef="replies">
<th mat-header-cell *matHeaderCellDef> Replies </th>
<ng-container *matCellDef="let hashtags">
<td mat-cell *ngIf="(hashtags.replies>0); else noReplies"> {{hashtags.replies}} </td>
</ng-container>
<ng-template #noReplies>-</ng-template>
</ng-container>
The reason for getting this error is because your can't put 2 structural directives on the same DOM
In your code, you were using *matCellDef and *ngIf on the same <td>.
you can do it this way...... xd
<ng-container matColumnDef="estadoRevision">
<mat-header-cell *matHeaderCellDef mat-sort-header>Revision</mat-header-cell>
<mat-cell *matCellDef="let element">
<td *ngIf="element.a === 0"> ejemplo </td>
<td *ngIf="element.a === 1"> ejemplo </td>
</mat-cell>
</ng-container>
Is there any reason you can't do the conditional directly in the interpolation?
<td mat-cell *matCellDef="let hashtags">{{hashtags.replies > 0 ? hashtag.replies : '-'}}</td>