Angular 2 material that implements sorting, filtering and pagination

I am trying to implement sorting, filtering and pagination using an md table. here is my code:

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; }); 

I want to return both of these values, but it only returns the sort function, the filter and pagination do not work.

  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); }); } 

How can I make sorting, filtering and pagination work?

+5
source share
2 answers

Edit on 01/29/2018 : an article was written about the material data table and can be seen here , it includes pagination, filtering and sorting servers and is probably more relevant than my code below, as many people visit this post. I think that this was a real need, I hope this helps you all, have fun.

Edit : the plunkr example no longer works, so I redefined it on stackblitz with the latest release of the material (starting with this change, beta 12) note: if you are using an older version of the material, you will need to change the mat prefix to md

Here is the updated version

This plunkr example (no longer works, see the link above for the working version) will show you a table with all the implementations you are looking for.

You can see how it is implemented during dependency injection:

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

Observable.merge(...displayDataChanges).map filters the data, the sortData() method sorts it, and paginator generates the number of pages depending on the length of the filtered data.

+16
source

This is what is used for pagination and sorting:

 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 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> 
+1
source

Source: https://habr.com/ru/post/1270219/


All Articles