I have an angular-material Data Table and I want it to align to a certain column left/right.
<mat-table #table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="col0">
<mat-header-cell *matHeaderCellDef mat-sort-header> Col0</mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.col0}} </mat-cell>
</ng-container>
<ng-container matColumnDef="col1">
<mat-header-cell *matHeaderCellDef mat-sort-header> Col1 </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.col1}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
What CSS do I need to do this?
After a few googling action I've found the solution in form of a github change request:
See here
The short form is like this:
.mat-column-col1 {
display: flex;
justify-content: flex-end;
}
Just replace the col1 to the column you're gonna need!
Related
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
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 am creating a table in angular and wish to fill it with data coming from an url . I have created a table following a tutorial. Code
dataSource : Parameters[]
getData(floor) {
console.log('Making a request')
this.vavService.getVavData(floor)
.subscribe(
(data11: any) => {
console.log(data11);
this.dataSource = data11;
console.log(this.dataSource)
}
)
}
parameters class
export class Parameters {
'date' : string;
'deviceID' : string;
'nvo_air_damper_position' : string;
'nvo_airflow' : string;
'nvo_temperature_sensor_pps' : string;
'timestamp' : string;
'vavID' : number;
'miloID' : string;
'miloTemperature' : number;
}
html code
<div>
<mat-table [dataSource]="dataSource">
<ng-container matColumnDef="date">
<mat-header-cell *matHeaderCellDef>Date</mat-header-cell>
<mat-cell *matCellDef="let policy"></mat-cell>
</ng-container>
<ng-container matColumnDef="deviceID">
<mat-header-cell *matHeaderCellDef>DeviceID</mat-header-cell>
<mat-cell *matCellDef="let policy"></mat-cell>
</ng-container>
<ng-container matColumnDef="damper">
<mat-header-cell *matHeaderCellDef>Damper Position</mat-header-cell>
<mat-cell *matCellDef="let policy"></mat-cell>
</ng-container>
<ng-container matColumnDef="airflow">
<mat-header-cell *matHeaderCellDef>Air Flow</mat-header-cell>
<mat-cell *matCellDef="let policy"></mat-cell>
</ng-container>
<ng-container matColumnDef="temperature">
<mat-header-cell *matHeaderCellDef>Temperature</mat-header-cell>
<mat-cell *matCellDef="let policy"></mat-cell>
</ng-container>
<ng-container matColumnDef="time">
<mat-header-cell *matHeaderCellDef>TimeStamp</mat-header-cell>
<mat-cell *matCellDef="let policy"></mat-cell>
</ng-container>
<ng-container matColumnDef="vavID">
<mat-header-cell *matHeaderCellDef>VAV ID</mat-header-cell>
<mat-cell *matCellDef="let policy"></mat-cell>
</ng-container>
<!-- <ng-container matColumnDef="miloID">
<mat-header-cell *matHeaderCellDef>Milo ID</mat-header-cell>
<mat-cell *matCellDef="let policy"></mat-cell>
</ng-container>
<ng-container matColumnDef="miloTemperature">
<mat-header-cell *matHeaderCellDef>Milo Temperature</mat-header-cell>
<mat-cell *matCellDef="let policy"></mat-cell>
</ng-container> -->
<mat-header-row *matHeaderRowDef="tableColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: tableColumns"></mat-row>
</mat-table>
</div>
when i load the component, api call is successful and i can see the data in the console. Also I see the table headers in the browser
0: {date: "2019-12-03", deviceId: "fd00::212:4b00:1957:d616", nvo_air_damper_position: "100.0", nvo_airflow: "0.0", nvo_temperature_sensor_pps: "327.6700134277344", …}
1: {date: "2019-12-03", deviceId: "fd00::212:4b00:1957:d616", nvo_air_damper_position: "100.0", nvo_airflow: "0.0", nvo_temperature_sensor_pps: "327.6700134277344", …}
But the data binding is not happening. Can someone help me with binding the data. Thanks
Try this, hope it helps:
Set the correct dataSource type:
dataSource: MatTableDatsSource<Parameters> = new MatTableDataSource<Parameters>([]);
and set the data like:
this.dataSource.data = data11;
I think you have to reference your table and call the renderRows() function when you use the data that way instead of using MatTableDataSource because initialy your value is empty and filled when your observable emit a value.
If a data array is provided, the table must be notified when the array's objects are added, removed, or moved. This can be done by calling the renderRows() function which will render the diff since the last table render. If the data array reference is changed, the table will automatically trigger an update to the rows.
At mat-table tag, add #table1 <mat-table #table1>
In your component
Add #ViewChild('table1', {static: false}) table: MatTable<any>;
Then after your set the data, call this.table.renderRows();
I try to show an empty message error when the filter doesn't have matches with:
<div *ngIf="dataSource.length === 0">No data</div>
but it doesn't work because I build a dynamic table with MatTableDataSource.
For a better understanding, I changed my dynamic table for an array predefined.
const ELEMENT_DATA: MembersElement[] = [
{ name: 'Jenny', age: 17 },
{ name: 'Daniel', age: 18 }
];
However, is necessary using MatTableDataSource to a dynamic building of the users' table
This is all my ts code.
import { Component, OnInit } from '#angular/core';
import {MatTableDataSource} from '#angular/material';
export interface SociosElement {
nombre: string;
edad: number;
}
const ELEMENT_DATA: MembersElement[] = [
{ name: 'Jenny', age: 17 },
{ name: 'Daniel', age: 18 }
];
#Component({
selector: 'app-pruebas',
templateUrl: './tableMembers.component.html',
styleUrls: ['./tableMembes.component.css']
})
export class PruebasComponent {
displayedColumns: string[] = ['name', 'age'];
dataSource = new MatTableDataSource(ELEMENT_DATA);
applyFilter(filterValue: string) {
this.dataSource.filter = filterValue.trim().toLowerCase();
}
}
This is my HTML code.
<mat-toolbar color="primary">My full table</mat-toolbar>
<mat-form-field>
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
<mat-table #table [dataSource]="dataSource">
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header>Name </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
</ng-container>
<ng-container matColumnDef="age">
<mat-header-cell *matHeaderCellDef mat-sort-header>Age </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.age}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;" (click)="row.toggle(row)">
</mat-row>
</mat-table>
<div *ngIf="dataSource.length === 0">No data</div>
You can't reach what you want using *ngIf="dataSource.length === 0" condition simply because the data source doesn't change at all when you do filtering. what you have to do is watch out for the filtered data length. you can use something like following:
*ngIf="dataSource.filteredData.length > 0" as the condition. the length of datasource.filteredData changes based on the filtered results. this condition can hide your table. you can put this in your table tag like:
<table mat-table [dataSource]="dataSource" *ngIf="dataSource.filteredData.length > 0">
One caveat to using ngIf. If you're using matSort and you nest the table inside a block using *ngIf, then the sorting will not work because the ngIf sets the viewChild to undefined. Reference
Use [ngClass] to get around this
<div [ngClass]="dataSource.filteredData.length > 0 ? 'visible': 'hidden'">
<mat-table #table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header>Name </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
</ng-container>
<ng-container matColumnDef="age">
<mat-header-cell *matHeaderCellDef mat-sort-header>Age </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.age}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;" (click)="row.toggle(row)">
</mat-row>
</mat-table>
</div>
<div [ngClass]="dataSource.filteredData.length > 0 ? 'hidden': 'visible'">
<tr>No results found.</tr>
</div>
Here is the CSS for the classes
.hidden {
visibility: hidden;
}
.visible {
visibility: visible;
}
For a mat-table, prior to v10, you could give the table a row of data when your dataSource is empty by doing this:
[dataSource]="dataSource.data.length > 0 && dataSource.data.filteredData > 0 ? dataSource : emptyDataSource"
Then create a column def for your cell to display the empty data message:
<ng-container vdlColumnDef="empty-row"> <td *matCellDef="let row" mat-cell [colSpan]="displayedColumns.length">No Data</td> </ng-container>
Then change your row def to show the empty row column def when dataSource is empty:
<tr mat-row *matRowDef="let row; columns: dataSource.data.length > 0 && dataSource.data.filteredData > 0 ? displayedColumns : ['empty-row'];">
https://stackblitz.com/edit/angular-mat-table-no-data?file=src%2Fapp%2Ftable-basic-flex-example.html
After Angular Material 10, they've added a directive for when there is no data in the table: 'If you want to show a message when not data matches the filter, you can use the *matNoDataRow directive.' https://v10.material.angular.io/components/table/overview#filtering
I am new to angular the following is the scenario:
I have a table with 10 columns.
Suppose I have different status like children,teen,young,adult,senior in column 4.
While displaying all records in Angular table, the records with senior status I need to display only 1,2,3& 4 columns with data and from 5-10 columns would be blank(actually there is data for these columns that is getting populated form data source but I need to show that as blank) and merged.
<mat-table #table [dataSource]="ds" matSort matSortDisableClear>
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition. -->
<!-- Request ID Column -->
<ng-container matColumnDef="id">
<mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">
Req Id
</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.id}} </mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="firstName">
<mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">
Name
</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.firstName}}<br />{{row.lastName}} </mat-cell>
</ng-container>
<!-- address Column -->
<ng-container matColumnDef="address">
<mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">
address
</mat-header-cell>
<mat-cell *matCellDef="let row">
{{row.address}}
</mat-cell>
</ng-container>
<!-- Status Column -->
<ng-container matColumnDef="status">
<mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">
Status
<mat-cell *matCellDef="let row">
{{row.status}} </mat-cell>
</ng-container>
....
<!-- Other 6 columns that needs to be merged similar to Id name and address -->
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
Thanks in advance
By using a ng-container like this for each column where we need to verify Removed status and display data based on that