'Angular 7 Sorting on Custom DataSource
I've got a custom DataSource that I've created in my Risk component to reach out to an API, retrieve a list of Risks and display them in a table. The table displays properly however my Sorting isn't working.
I'm not entirely sure why however I call a refresh on the page every time the sort-able header is clicked, yet nothing. I've tried several different examples & configurations and I'm missing something.
Here's my risk.component.ts
export class RiskDashboardComponent implements AfterViewInit, OnInit {
@ViewChild(MatSort) sort: MatSort;
dataSource: RiskDataSource;
displayedColumns = ['riskName'];
constructor(private riskService: RiskManagmentService) {}
ngOnInit() {
this.dataSource = new RiskDataSource(this.riskService);
this.dataSource.loadRisks();
}
ngAfterViewInit() {
merge(this.sort.sortChange).pipe(
tap(() => this.loadRisksPage())
)
.subscribe();
}
loadRisksPage() {
this.dataSource.loadRisks();
}
}
export class RiskDataSource implements DataSource<IRisk> {
private risksSubject = new BehaviorSubject<IRisk[]>([]);
private loadingSubject = new BehaviorSubject<boolean>(false);
constructor(private riskService: RiskManagmentService) {}
connect(collectionViewer: CollectionViewer): Observable<IRisk[]> {
return this.risksSubject.asObservable();
}
disconnect(collectionViewer: CollectionViewer): void {
this.risksSubject.complete();
this.loadingSubject.complete();
}
loadRisks() {
this.loadingSubject.next(true);
this.riskService.getAllRisks().subscribe(risk => this.risksSubject.next(risk));
}
}
The risk.component.html
<div>
<mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource"
matSort matSortActive="riskName">
<ng-container matColumnDef="riskName">
<mat-header-cell *matHeaderCellDef mat-sort-header> Risk Name </mat-header-cell>
<mat-cell *matCellDef="let risk"> {{risk.riskRegister.riskName}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
(inb4 missing div tag, its in there, just isn't showing)
Every time the Risk Name order arrow is clicked it queries the database again for the list of risks
Any help would be greatly appreciated!
Solution 1:[1]
As you are using your own datasource most of the example in the angular material documentation website does not apply to you.
Firstly, you need to get the matsort from the view child and pass it into the datasource.
RiskDashBoardComponent
Add this
ViewChild(MatSort) sort: MatSort;
ngOnInit() {
this.dataSource = new RiskDataSource(this.riskService, this.sort);
this.dataSource.loadRisks();
}
You will require a little knowledge of observables here.
Now you need to return an observable that listen to two things by merging them. So when either the risksSubject gets a new data or mat sort is emitting new sort sequence you will handle the data always by getting the current value of the sort direction and the current value of the risksSubject.
You can see how to implement a custom sortData function from the angular material documentation site.
https://material.angular.io/components/sort/examples
RiskDataSource
connect(collectionViewer: CollectionViewer): Observable<IRisk[]> {
const displayDataChanges = [
this.risksSubject,
this._sort.sortChange
];
merge(...displayDataChanges).pipe(map(() => {
return this.sortData(this.risksSubject.getValue());
}));
}
loadRisks() {
this.loadingSubject.next(true);
this.riskService.getAllRisks().subscribe(risk =>
this.risksSubject.next(risk));
}
**
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | chronolegend |