J'essaie d'implémenter le tri, le filtre et la pagination en utilisant md-table . Voici mon 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;
});
Je veux renvoyer ces deux valeurs mais elle ne renvoie que la fonction de tri que le filtre et la pagination ne fonctionnent pas.
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);
});
}
Comment puis-je faire en sorte que le tri, le filtre et la pagination fonctionnent?
Edition du 29/01/2018: un article sur la table de données sur les matériaux a été écrit et peut être vu ici , il inclut la pagination, le filtrage et le tri des serveurs et est probablement plus à jour que mon code ci-dessous, étant donné que de nombreuses personnes visitent cet article, je suppose que cela était vraiment nécessaire. J'espère que cela vous aidera à tous, amusez-vous.
Edit: l'exemple plunkr ne fonctionne plus, je l'ai donc réimplémenté sur stackblitz avec la version la plus récente (à partir de cette édition, version 12) Note: si vous utilisez une version plus ancienne du matériel dont vous aurez besoin changer les préfixes mat
en md
Cet exemple de plunkr (ne fonctionne plus, voir le lien ci-dessus pour une version opérationnelle) vous montrera le tableau avec toutes les implémentations que vous recherchez.
Vous pouvez voir comment cela est implémenté avec l'injection de dépendance:
const displayDataChanges = [
this._exampleDatabase.dataChange,
this._sort.mdSortChange,
this._filterChange,
this._paginator.page,
];
La Observable.merge(...displayDataChanges).map
filtre les données, la méthode sortData()
les trie et la pagination génère le nombre de pages en fonction de la longueur des données filtrées.
C'est ce que l'utilisation pour la pagination et le tri:
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>