I am trying to use the Angular Material Table with selection, it says on the browser console 'data' is undefined here . The error on the console says "Cannot read property 'data' of undefined in Material Table with selection" however the table is displayed with the data from Json file.
Here is the full code for the .ts file
export class GetUserComponent implements OnInit
isFetching = false;
displayedColumns: string[] = ['select','title','content'];
dataSource : MatTableDataSource<User>;
selection = new SelectionModel<User>(true, []);
constructor(private http: HttpClient, private userService : UserService) { }
/** Whether the number of selected elements matches the total number of rows. */
isAllSelected() {
const numSelected = this.selection.selected.length;
**const numRows = this.dataSource.data.length;**
return numSelected === numRows;
}
/** Selects all rows if they are not all selected; otherwise clear selection. */
masterToggle() {
this.isAllSelected() ?
this.selection.clear() :
this.dataSource.data.forEach(row => this.selection.select(row));
}
/** The label for the checkbox on the passed row */
checkboxLabel(row?: User): string {
if (!row) {
return `${this.isAllSelected() ? 'select' : 'deselect'} all`;
}
return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.id + 1}`;
}
This is the HTML table
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox (change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()"
[aria-label]="checkboxLabel()">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let row">
<mat-checkbox (click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(row) : null"
[checked]="selection.isSelected(row)"
[aria-label]="checkboxLabel(row)">
</mat-checkbox>
</td>
</ng-container>
<!-- Position Column -->
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Title </th>
<td mat-cell *matCellDef="let element"> {{element.title}} </td>
</ng-container>
<ng-container matColumnDef="content">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Content </th>
<td mat-cell *matCellDef="let element"> {{element.content}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
(click)="selection.toggle(row)">
</tr>
</table>
Please advise on this.
This thing worked for me: Import table
from angular/material
and create an
instance of it using viewchild
. Get your user data and set displayedColumns
in
ngOnInit()
. In ngAfterContentChecked()
you need to create a MatTableDataSource
instance and set this instance to table.dataSource
in ngAfterViewInit()
. See below:
import { MatTable, MatTableDataSource } from '@angular/material/table';
export class GetUserComponent implements OnInit {
@ViewChild(MatTable, {static:false}) table: MatTable<any>;
dataSource :any;
constructor(private appService:AppService){}
ngOnInit() {
this.appService.getUsers().subscribe(data => {
this.userData= data;
});
this.displayedColumns = ['select','title','content'];
}
ngAfterViewInit() {
this.table.dataSource = this.dataSource;
}
ngAfterContentChecked() {
this.dataSource = new MatTableDataSource (this.userData);
}
}
You can check my stackblitz here: https://stackblitz.com/edit/angular-dynamicexamples