【问题标题】:Angular 2 material implementing sort, filter and paginationAngular 2 材料实现排序、过滤和分页
【发布时间】:2018-01-01 19:41:33
【问题描述】:

我正在尝试使用 md-table 实现排序、过滤和分页。 这是我的代码:

connect(): Observable<Patient[]> {
const displayPatientDataChanges = [
  this._patientDatabase.dataChange,
  this._filterPatientChange,
  this._paginator.page,
  this._sort.mdSortChange,
];

return Observable.merge(...displayPatientDataChanges).map(() => {
  const startIndex = this._paginator.pageIndex * this._paginator.pageSize;

  let displayData = this._patientDatabase.data.slice().filter((item: Patient) => {
    let searchStr = (item.firstname + ' ' + item.lastname).toLowerCase();
    return searchStr.indexOf(this.filter.toLowerCase()) != -1;
  });

我想返回这两个值,但它只返回排序函数,过滤器和分页不起作用。

  return displayData.splice(startIndex, this._paginator.pageSize),this.getSortedData();


});

}

 disconnect() { }

getSortedData(): Patient[] {
const data = this._patientDatabase.data.slice();
if (!this._sort.active || this._sort.direction == '') { return data; }

return data.sort((a, b) => {
  let propertyA: number|string|Date = '';
  let propertyB: number|string|Date = '';

  switch (this._sort.active) {
    case 'id': [propertyA, propertyB] = [a.id, b.id]; break;
    case 'firstname': [propertyA, propertyB] = [a.firstname, b.firstname]; break;
    case 'lastname': [propertyA, propertyB] = [a.lastname, b.lastname]; break;
    case 'dateOfBirth': [propertyA, propertyB] = [a.dateOfBirth, b.dateOfBirth]; break;
    case 'sex': [propertyA, propertyB]= [a.sex, b.sex]; break;
    case 'dateAdded': [propertyA, propertyB] = [a.dateAdded, b.dateAdded]; break;
  }

  let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
  let valueB = isNaN(+propertyB) ? propertyB : +propertyB;

  return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : 1);
});
 }

如何使排序、过滤和分页起作用?

【问题讨论】:

    标签: angular sorting pagination angular-material2


    【解决方案1】:

    编辑于 01/29/2018 :已经写了一篇关于材质数据表的文章,可以看到here,它包括服务器分页、过滤和排序,可能更高级-迄今为止比我下面的代码,因为很多人都在访问这篇文章,我想确实需要这个,希望它对大家有帮助,玩得开心。

    编辑:plunkr 示例不再起作用,因此我在 stackblitz 上使用最新的材料版本重新实现了它(截至本次编辑,beta 12) 注意:如果您使用的是旧版本的材料,您需要将 mat 前缀改回 md

    Here is the updated version

    这个plunkr example(不再工作,请参阅上面的链接以获取工作版本)将向您显示包含您正在寻找的所有实现的表格。

    你可以看到它是如何通过依赖注入实现的:

        const displayDataChanges = [
      this._exampleDatabase.dataChange,
      this._sort.mdSortChange, 
      this._filterChange,
      this._paginator.page,
    ];
    

    Observable.merge(...displayDataChanges).map 过滤数据,sortData() 方法对其进行排序,分页器根据过滤数据的长度生成页数。

    【讨论】:

    • 有没有人找到一些使用服务器端分页的好方法?谢谢!
    • 我什至不好意思问,但是否有一个类似于此 plunkr 的示例,其中使用通过服务从数据库返回的数据代替 ExampleDatabase?我不知道如何分矿。
    • @Greg 我用新链接更新了我的答案,这是在材料 beta 12 上运行的工作版本
    • @user2748659 plunkr 不断将软件包更新到最新版本,在某些时候你最终会遇到向后兼容性问题
    • 似乎您的分页器未定义,请确保您在app.module 中添加了导入,在您的@angular/material 导入列表中检查MatPaginatorModule 是否在其中。
    【解决方案2】:

    这就是分页和排序的用途:

    import { Component, OnInit } from '@angular/core';
    import { ViewChild, Output, EventEmitter } from '@angular/core';
    import { DataSource } from '@angular/cdk';
    import { MdPaginator, MdSort } from '@angular/material';
    import { BehaviorSubject } from 'rxjs/BehaviorSubject';
    import { Observable } from 'rxjs/Observable';
    import 'rxjs/add/operator/startWith';
    import 'rxjs/add/observable/merge';
    import 'rxjs/add/operator/map';
    import { SharedService } from "app/services/shared.service";
    
    @Component({
      selector: 'app-rtable',
      styleUrls: ['./rtable.component.css'],
      templateUrl: './rtable.component.html',
    })
    export class RtableComponent {
      displayedColumns = ['userId', 'userName', 'progress', 'color', 'url'];
      exampleDatabase = new ExampleDatabase();
      dataSource: ExampleDataSource | null;
    
      @ViewChild(MdPaginator) paginator: MdPaginator;
      @ViewChild(MdSort) sort: MdSort;
      @Output()
      playAudioPlayer: EventEmitter<string> = new EventEmitter();
    
      constructor(private _sharedService: SharedService) { }
    
      ngOnInit() {
     
      }
    }
    
    const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple',
      'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray'];
    const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack',
      'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper',
      'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth'];
    const URLS = ['http://localhost/ragnar1.mp3', 'http://localhost/ragnar1.mp3',
      'http://localhost/ragnar1.mp3', 'http://localhost/ragnar1.mp3',
      'http://localhost/ragnar2.mp3', 'http://localhost/ragnar2.mp3',
      'http://localhost/ragnar3.mp3', 'http://localhost/ragnar3.mp3',
      'http://localhost/ragnar1.mp3', 'http://localhost/ragnar1.mp3',
      'http://localhost/ragnar2.mp3', 'http://localhost/ragnar2.mp3',
      'http://localhost/ragnar3.mp3', 'http://localhost/ragnar3.mp3',
      'http://localhost/ragnar1.mp3', 'http://localhost/ragnar1.mp3',
      'http://localhost/ragnar2.mp3', 'http://localhost/ragnar2.mp3',
      'http://localhost/ragnar3.mp3'];
    
    export interface UserData {
      id: string;
      name: string;
      progress: string;
      color: string;
      url: string;
    }
    export class ExampleDatabase {
      /** Stream that emits whenever the data has been modified. */
      dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
      get data(): UserData[] { return this.dataChange.value; }
    
      constructor() {
        // Fill up the database with 100 users.
        for (let i = 0; i < 100; i++) { this.addUser(); }
      }
    
      /** Adds a new user to the database. */
      addUser() {
        const copiedData = this.data.slice();
        copiedData.push(this.createNewUser());
        this.dataChange.next(copiedData);
      }
    
      /** Builds and returns a new User. */
      private createNewUser() {
        const name =
          NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' +
          NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.';
    
        return {
          id: (this.data.length + 1).toString(),
          name: name,
          progress: Math.round(Math.random() * 100).toString(),
          color: COLORS[Math.round(Math.random() * (COLORS.length - 1))],
          url: URLS[Math.round(Math.random() * (URLS.length - 1))]
        };
      }
    }
    
    export class ExampleDataSource extends DataSource<any> {
      constructor(private _exampleDatabase: ExampleDatabase, private _paginator: MdPaginator, private _sort: MdSort) {
        super();
      }
    
      /** Connect function called by the table to retrieve one stream containing the data to render. */
      connect(): Observable<UserData[]> {
        const displayDataChanges = [
          this._exampleDatabase.dataChange,
          this._paginator.page,
          this._sort.mdSortChange
        ];
    
        return Observable.merge(...displayDataChanges).map(() => {
          const data = this.getSortedData();
    
          // Grab the page's slice of data.
          const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
          return data.splice(startIndex, this._paginator.pageSize);
        });
      }
    
      disconnect() { }
    
      /** Returns a sorted copy of the database data. */
      getSortedData(): UserData[] {
        const data = this._exampleDatabase.data.slice();
        if (!this._sort.active || this._sort.direction == '') { return data; }
    
        return data.sort((a, b) => {
          let propertyA: number | string = '';
          let propertyB: number | string = '';
    
          switch (this._sort.active) {
            case 'userId': [propertyA, propertyB] = [a.id, b.id]; break;
            case 'userName': [propertyA, propertyB] = [a.name, b.name]; break;
            case 'progress': [propertyA, propertyB] = [a.progress, b.progress]; break;
            case 'color': [propertyA, propertyB] = [a.color, b.color]; break;
            case 'url': [propertyA, propertyB] = [a.url, b.url]; break;
          }
    
          let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
          let valueB = isNaN(+propertyB) ? propertyB : +propertyB;
    
          return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : -1);
        });
      }
    
    
    }
    /* Structure */
    .example-container {
      display: flex;
      flex-direction: column;
      max-height: 500px;
      min-width: 300px;
    }
    
    .example-header {
      min-height: 64px;
      display: flex;
      align-items: center;
      padding-left: 24px;
      font-size: 20px;
    }
    
    .mat-table {
      overflow: auto;
    }
    md-row:hover{
      background-color: #f3f3f3;
    }
    <div class="example-container mat-elevation-z8">
    
      <md-table #table mdSort [dataSource]="dataSource">
    
        <!--- Note that these columns can be defined in any order.
              The actual rendered columns are set as a property on the row definition" -->
        <md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
        <md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
    
        <!-- ID Column -->
        <ng-container cdkColumnDef="userId">
          <md-header-cell *cdkHeaderCellDef md-sort-header> ID </md-header-cell>
          <md-cell *cdkCellDef="let row"> {{row.id}} </md-cell>
        </ng-container>
    
        <!-- Progress Column -->
        <ng-container cdkColumnDef="progress">
          <md-header-cell *cdkHeaderCellDef md-sort-header> Progress </md-header-cell>
          <md-cell *cdkCellDef="let row"> {{row.progress}}% </md-cell>
        </ng-container>
    
        <!-- Name Column -->
        <ng-container cdkColumnDef="userName">
          <md-header-cell *cdkHeaderCellDef md-sort-header> Name </md-header-cell>
          <md-cell *cdkCellDef="let row"> {{row.name}} </md-cell>
        </ng-container>
    
        <!-- Color Column -->
        <ng-container cdkColumnDef="color">
          <md-header-cell *cdkHeaderCellDef md-sort-header> Color </md-header-cell>
          <md-cell *cdkCellDef="let row" [style.color]="row.color"> {{row.color}} </md-cell>
        </ng-container>
    
        <!-- Url Column -->
        <ng-container cdkColumnDef="url">
          <md-header-cell *cdkHeaderCellDef md-sort-header> Audio </md-header-cell>
          <md-cell *cdkCellDef="let row" >
             <button md-button (click)="callAudioEvent(row.url)" [style.color]="row.color">Listen..</button>
            </md-cell>
        </ng-container>
    
      </md-table>
    
      <md-paginator #paginator [length]="exampleDatabase.data.length" [pageIndex]="0" [pageSize]="5" [pageSizeOptions]="[5, 10, 25,50, 100]">
      </md-paginator>
    </div>

    【讨论】:

      猜你喜欢
      • 2018-06-22
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 2020-04-08
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多