I´m doing a table component.
This component works perfectly without sortable functionnality.
When I´m trying to make the table sortable, that works if I´m using basic example when you store the object list in a constant but rows do not display when I´m trying to use @Input()
Version with constant - That works
import {AfterContentInit, AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core';
import {Client, ClientStatus} from '@models/client.model';
import {ClientService} from '@services/client.service';
import {MatSort, Sort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';
const ELEMENT_DATA: Client[] = [
...
];
@Component({
selector: 'app-table-entries',
templateUrl: './table-entries.component.html',
styleUrls: ['./table-entries.component.scss']
})
export class TableEntriesComponent implements OnInit, AfterViewInit {
displayedColumns: string[] = ['expectedDate', 'description.id', 'priority' ];
@ViewChild(MatSort, {static: true}) sort: MatSort;
sortableEntries = new MatTableDataSource(ELEMENT_DATA);
constructor( clientService: ClientService ) {}
ngOnInit(): void {}
ngAfterViewInit() {
this.sort.active = 'expectedDate';
this.sort.direction = 'asc';
this.sortableEntries.sort = this.sort;
this.sortableEntries.sortingDataAccessor = ( client, property) => {
switch ( property ) {
case 'description.id': return client.description.id;
default: return client[property];
}
};
}
}
Version with @Input - That does not work
import {AfterContentInit, AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core';
import {Client, ClientStatus} from '@models/client.model';
import {ClientService} from '@services/client.service';
import {MatSort, Sort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';
@Component({
selector: 'app-table-entries',
templateUrl: './table-entries.component.html',
styleUrls: ['./table-entries.component.scss']
})
export class TableEntriesComponent implements OnInit, AfterViewInit {
@Input() entries: Client[] = [];
displayedColumns: string[] = ['expectedDate', 'description.id', 'priority' ];
@ViewChild(MatSort, {static: true}) sort: MatSort;
sortableEntries: MatTableDataSource<Client>;
constructor( clientService: ClientService ) {}
ngOnInit(): void {
this.sortableEntries = new MatTableDataSource<Client>( this.entries );
}
ngAfterViewInit() {
this.sort.active = 'expectedDate';
this.sort.direction = 'asc';
this.sortableEntries.sort = this.sort;
this.sortableEntries.sortingDataAccessor = ( client, property) => {
switch ( property ) {
case 'description.id': return client.description.id;
default: return client[property];
}
};
}
}
Template
<table mat-table matSort [dataSource]="sortableEntries">
<!-- Heure RDV -->
<ng-container matColumnDef="expectedDate">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Heure rdv </th>
<td mat-cell *matCellDef="let element"> {{ element.expectedDate | date: "d/M HH:mm" }} </td>
</ng-container>
<!-- Identifiant -->
<ng-container matColumnDef="description.id">
<th mat-header-cell *matHeaderCellDef mat-sort-header="description.id"> Identifiant </th>
<td mat-cell *matCellDef="let element"> {{ element.description.id}} </td>
</ng-container>
<!-- Nature -->
<ng-container matColumnDef="priority">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Nature </th>
<td mat-cell *matCellDef="let element" > {{ element.priority | getStringPriority }} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; let even = even; columns: displayedColumns;" [ngClass]="{ 'table-even-row': even}"></tr>
</table>
<section *ngIf="entries && entries.length === 0" class="no-client-wrapper"><p>Il n'y a pas d'entrée actuellement</p></section>
I can imagine the problem is the moment when the object list is loaded but I don´t know how to fix this. Someone has got an idea ?
I found a solution here.
First of all, change @Input() entries: Client[] = [];
by
@Input() set entries( data: Client[] ) {
this.setTableDataSource(data);
}
Then, Use the content in ngAfterViewInit to make the function
setTableDataSource(data: any) {
this.sortableEntries = new MatTableDataSource<any>(data);
this.sortableEntries.sort = this.sort;
this.sort.active = 'expectedDate';
this.sort.direction = 'asc';
this.sortableEntries.sortingDataAccessor = ( client, property) => {
switch ( property ) {
case 'description.codeUT': return client.description.codeUT;
default: return client[property];
}
};
}
Complete result
import {AfterContentInit, AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core';
import {Client, ClientStatus} from '@models/client.model';
import {ClientService} from '@services/client.service';
import {MatSort, Sort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';
@Component({
selector: 'app-table-entries',
templateUrl: './table-entries.component.html',
styleUrls: ['./table-entries.component.scss']
})
export class TableEntriesComponent implements OnInit{
displayedColumns: string[] = ['expectedDate', 'description.id', 'priority' ];
@ViewChild(MatSort, {static: true}) sort: MatSort;
sortableEntries: MatTableDataSource<Client>;
@Input() set entries( data: Client[] ) {
this.setTableDataSource(data);
}
setTableDataSource(data: any) {
this.sortableEntries = new MatTableDataSource<any>(data);
this.sortableEntries.sort = this.sort;
this.sort.active = 'expectedDate';
this.sort.direction = 'asc';
this.sortableEntries.sortingDataAccessor = ( client, property) => {
switch ( property ) {
case 'description.id': return client.description.id;
default: return client[property];
}
};
}
constructor( clientService: ClientService ) {
this.sortableEntries = new MatTableDataSource<Client>( this.entries );
}
ngOnInit(): void {
console.dir( this.entries );
}
}