简体   繁体   中英

Sort table data with Angular Material

I have setup a component using Angular and Material. I have the data I want exposed correctly using the BitBucket status API: https://bitbucket.status.atlassian.com/api#status

I am just stuck on how to enable sort on the columns, I would like to sort all 3 using the default settings. Any direction would be appreciated.

Here is a stackblitz: https://stackblitz.com/edit/angular-gmdy9j

HTML:

<div class="example-table-container">

    <table mat-table [dataSource]="data"
           matSort matSortActive="name" matSortDirection="desc">


      <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Name</th>
        <td mat-cell *matCellDef="let row">{{row.name}}</td>
      </ng-container>


      <ng-container matColumnDef="status">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Status</th>
        <td mat-cell *matCellDef="let row">{{row.status}}</td>
      </ng-container>


      <ng-container matColumnDef="created_at">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>
          Created
        </th>
        <td mat-cell *matCellDef="let row">{{row.created_at | date}}</td>
      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>

  </div>

TS:

import {HttpClient} from '@angular/common/http';
import {Component, ViewChild, AfterViewInit} from '@angular/core';
import {MatSort} from '@angular/material';
import {merge, Observable, of as observableOf} from 'rxjs';
import {catchError, map, startWith, switchMap} from 'rxjs/operators';

@Component({
  selector: 'app-headlines',
  templateUrl: './headlines.component.html',
  styleUrls: ['./headlines.component.scss']
})

export class HeadlinesComponent implements AfterViewInit {
  displayedColumns: string[] = ['name', 'status', 'created_at'];
  tableDatabase: TableHttpDatabase | null;
  data: BitBucketIssue[] = [];

  resultsLength = 0;
  isLoadingResults = true;


  @ViewChild(MatSort) sort: MatSort;

  constructor(private http: HttpClient) {}

  ngAfterViewInit() {
    this.tableDatabase = new TableHttpDatabase(this.http);

    merge(this.sort.sortChange)
      .pipe(
        startWith({}),
        switchMap(() => {
          this.isLoadingResults = true;
          return this.tableDatabase!.getRepoIssues(
            this.sort.active, this.sort.direction);
        }),
        map(data => {

          // Flip flag to show that loading has finished.
          this.isLoadingResults = false;
          this.resultsLength = data.incidents.length;
          console.log(data.incidents.length)
          console.log(data.incidents)
          return data.incidents;

        }),
        catchError(() => {
          this.isLoadingResults = false;
          return observableOf([]);
        })
      ).subscribe(data => this.data = data);
  }
}

export interface BitBucketApi {
  incidents: BitBucketIssue[];
}

export interface BitBucketIssue {
  name: string;
  status: string;
  created_at: number;
}

/** An example database that the data source uses to retrieve data for the table. */
export class TableHttpDatabase {
  constructor(private http: HttpClient) {}

  getRepoIssues(sort: string, order: string): Observable<BitBucketApi> {
    const href = 'https://bqlf8qjztdtr.statuspage.io/api/v2/incidents.json';
    const requestUrl =
        `${href}?q=&sort=${sort}&order=${order}`;

    return this.http.get<BitBucketApi>(requestUrl);
  }
}

Here is a stackblitz: https://stackblitz.com/edit/angular-gmdy9j

Seems that you were not linking the required MatTableDataSource to your retrieved data. You need to assign your MatSort element to the MatTableDataSource sort property, and use the MatTableDataSource to display the data. All well documented in the official documentation https://material.angular.io/components/sort/overview

ANGULAR CODE

import {HttpClient} from '@angular/common/http';
import {Component, ViewChild, AfterViewInit} from '@angular/core';
import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material';
import {merge, Observable, of as observableOf} from 'rxjs';
import {catchError, map, startWith, switchMap} from 'rxjs/operators';

/**
 * @title Table retrieving data through HTTP
 */
@Component({
  selector: 'table-http-example',
  styleUrls: ['table-http-example.css'],
  templateUrl: 'table-http-example.html',
})
export class TableHttpExample implements AfterViewInit {
  displayedColumns: string[] = ['name', 'status', 'created_at'];
  tableDatabase: TableHttpDatabase | null;
  data: BitBucketIssue[] = [];
  dataSource: MatTableDataSource<BitBucketIssue>;

  resultsLength = 0;
  isLoadingResults = true;


  @ViewChild(MatSort) sort: MatSort;

  constructor(private http: HttpClient) {}

  ngAfterViewInit() {
    this.tableDatabase = new TableHttpDatabase(this.http);

    merge(this.sort.sortChange)
      .pipe(
        startWith({}),
        switchMap(() => {
          this.isLoadingResults = true;
          return this.tableDatabase!.getRepoIssues(
            this.sort.active, this.sort.direction);
        }),
        map(data => {

          // Flip flag to show that loading has finished.
          this.isLoadingResults = false;
          this.resultsLength = data.incidents.length;
          console.log(data.incidents.length)
          console.log(data.incidents)
          return data.incidents;

        }),
        catchError(() => {
          this.isLoadingResults = false;
          return observableOf([]);
        })
      ).subscribe(data => {
        this.data = data; this.dataSource = new MatTableDataSource(data);
        this.dataSource.sort = this.sort;
      });
  }
}

export interface BitBucketApi {
  incidents: BitBucketIssue[];
}

export interface BitBucketIssue {
  name: string;
  status: string;
  created_at: number;
}

/** An example database that the data source uses to retrieve data for the table. */
export class TableHttpDatabase {
  constructor(private http: HttpClient) {}

  getRepoIssues(sort: string, order: string): Observable<BitBucketApi> {
    const href = 'https://bqlf8qjztdtr.statuspage.io/api/v2/incidents.json';
    const requestUrl =
        `${href}?q=&sort=${sort}&order=${order}`;

    return this.http.get<BitBucketApi>(requestUrl);
  }
}

HTML

<div class="example-table-container">

    <table mat-table [dataSource]="dataSource"
           matSort matSortActive="name" matSortDirection="desc">

      <!-- Title Column -->
      <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Name</th>
        <td mat-cell *matCellDef="let row">{{row.name}}</td>
      </ng-container>

      <!-- State Column -->
      <ng-container matColumnDef="status">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Status</th>
        <td mat-cell *matCellDef="let row">{{row.status}}</td>
      </ng-container>

      <!-- Created Column -->
      <ng-container matColumnDef="created_at">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>
          Created
        </th>
        <td mat-cell *matCellDef="let row">{{row.created_at | date}}</td>
      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>

  </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM