Reputation: 527
Trying to sort my data and for some reason it's not working. All examples use a local array of values, while mine is an API call which returns an array of objects, of which, each item has a 'name' property.
I can load the page and see the sort header arrow but clicking doesn't produce a change. I'm using a function call to get my 'clients' and calling that in the constructor, but it's failed for me in both OnInit as well. I have also checked that my column def is identical to my data field returned, namely 'name' but that's not helping either.
------ TS ---------
import { Component, OnInit, ViewChild } from "@angular/core";
import { Router } from "@angular/router";
import { ClientService } from "../../../core/services/client.service";
import { Client } from "../../../core/models/client.interface";
import { MatDialog, MatDialogConfig } from "@angular/material/dialog";
import { ClientDialogComponent } from "../client-dialog/client-dialog.component";
import { ConfirmDeleteDialogComponent } from "../../../core/components/confirm-delete-dialog/confirm-delete-dialog.component";
import { SnackbarService } from "src/app/core/services/snackbar.service";
import { MatTableDataSource } from "@angular/material/table";
import { MatSort } from "@angular/material/sort";
@Component({
templateUrl: "./clients.component.html",
styleUrls: ["./clients.component.css"],
})
export class ClientsComponent implements OnInit {
dataSource: MatTableDataSource<Client[]>;
client: Client;
tableColumns: string[] = ["name", "website", "phone", "actions"];
@ViewChild(MatSort) sort: MatSort;
constructor(
private _clientService: ClientService,
private _router: Router,
private _snackbar: SnackbarService,
public dialog: MatDialog
) {
this.getClients();
}
ngOnInit() {
this.dataSource.sort = this.sort;
}
getClients() {
// Get clients from API
this._clientService.getClients().subscribe(
(response) => {
this.dataSource = new MatTableDataSource(response); <----- this is simple array of objects
},
(error) => {
this._snackbar.show(error["message"], "warn-snackbar");
}
);
}
}
-------- HTML --------------
<div *ngIf="dataSource; else spinner">
<div class="row">
<div class="search">
<mat-form-field>
<input type="text" matInput placeholder="Filter" (keyup)="applyFilter($event.target.value)">
</mat-form-field>
</div>
<div class="col-button">
<button *hasClaim="'canAddClient'" type="button" mat-stroked-button color="primary" class="add-client-button"
(click)="addClientDialog()">
Add Client
</button>
</div>
</div>
<div class="row">
<div class="col-table">
<table mat-table [dataSource]="dataSource" matSort>
<!-- row / column definitions -->
<tr mat-header-row *matHeaderRowDef="tableColumns" [ngClass]="'table-header'"></tr>
<tr mat-row *matRowDef="let row; columns: tableColumns">
</tr>
<!-- client -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Client</th>
<td mat-cell *matCellDef="let client"> {{client.name}} </td>
</ng-container>
<!-- website -->
<ng-container matColumnDef="website">
<th mat-header-cell *matHeaderCellDef>Website</th>
<td mat-cell *matCellDef="let client"> {{client.website}} </td>
</ng-container>
<!-- phone -->
<ng-container matColumnDef="phone">
<th mat-header-cell *matHeaderCellDef>Phone</th>
<td mat-cell *matCellDef="let client"> {{client.phone | formatPhone}} </td>
</ng-container>
<!-- actions -->
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>Actions</th>
<td mat-cell *matCellDef="let client">
<button mat-stroked-button class="action-button" color="primary" (click)="goToDetailsPage(client._id)">
Info
</button>
<button *hasClaim="'canEditClient'" mat-stroked-button class="action-button" color="primary"
(click)="editClientDialog(client)">
Edit
</button>
<button *hasClaim="'canDeleteClient'" mat-stroked-button class="action-button" color="warn"
(click)="deleteClientDialog(client)">
Delete
</button>
</td>
</ng-container>
</table>
</div>
</div>
</div>
<ng-template #spinner>
<mat-spinner></mat-spinner>
</ng-template>
Upvotes: 0
Views: 97
Reputation: 403
I think your issue is happening because you are setting the sort on the dataSource
before the ViewChild
is defined. There are two ways that should fix this:
Add {static: true}
to your @ViewChild
definition as below:
@ViewChild(MatSort, {static: true}) sort: MatSort;
This causes the Angular to eagerly fetch the MatSort
element, so it is available in ngOnInit
.
Move the sort assignment into ngAfterViewInit
. In the code you provided, you can rename the ngOnInit
function to ngAfterViewInit
. This works because non-static ViewChild
objects are available in ngAfterViewInit
.
If you're interested, you can read up on the difference between ngOnInit
and ngAfterViewInit
and the static
flag to ViewChild
.
Upvotes: 1
Reputation: 81
Why don't you create your table from CLI ? It packs a lot of functionality by default and saves a lot of time as well.
There you can hit your API and store the data, pretty straight forward process. For your current table, I don't know why it's not working properly
Upvotes: 0