2017-08-01 72 views
0

如何結合使用材料設計表的輸入和排序列過濾?排序列和過濾輸入是否可以使用相同的方法connect()?角度材料結合輸入過濾器和排序列

我從https://material.angular.io/components/table/overview

的例子,我不知道該怎麼做,因爲兩個過濾和排序用同樣的方法,並在這些例子中顯示的方法連接必須有排序和篩選不同勢實現。

實施例具有輸入過濾:

import {Component, ElementRef, ViewChild} from '@angular/core'; 
import {DataSource} from '@angular/cdk'; 
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 'rxjs/add/operator/debounceTime'; 
import 'rxjs/add/operator/distinctUntilChanged'; 
import 'rxjs/add/observable/fromEvent'; 

@Component({ 
    selector: 'table-filtering-example', 
    styleUrls: ['table-filtering-example.css'], 
    templateUrl: 'table-filtering-example.html', 
}) 
export class TableFilteringExample { 
    displayedColumns = ['userId', 'userName', 'progress', 'color']; 
    exampleDatabase = new ExampleDatabase(); 
    dataSource: ExampleDataSource | null; 

    @ViewChild('filter') filter: ElementRef; 

    ngOnInit() { 
    this.dataSource = new ExampleDataSource(this.exampleDatabase); 
    Observable.fromEvent(this.filter.nativeElement, 'keyup') 
     .debounceTime(150) 
     .distinctUntilChanged() 
     .subscribe(() => { 
      if (!this.dataSource) { return; } 
      this.dataSource.filter = this.filter.nativeElement.value; 
     }); 
    } 
} 

/** Constants used to fill up our data base. */ 
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']; 

export interface UserData { 
    id: string; 
    name: string; 
    progress: string; 
    color: string; 
} 

/** An example database that the data source uses to retrieve data for the table. */ 
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))] 
    }; 
    } 
} 

/** 
* Data source to provide what data should be rendered in the table. Note that the data source 
* can retrieve its data in any way. In this case, the data source is provided a reference 
* to a common data base, ExampleDatabase. It is not the data source's responsibility to manage 
* the underlying data. Instead, it only needs to take the data and send the table exactly what 
* should be rendered. 
*/ 
export class ExampleDataSource extends DataSource<any> { 
    _filterChange = new BehaviorSubject(''); 
    get filter(): string { return this._filterChange.value; } 
    set filter(filter: string) { this._filterChange.next(filter); } 

    constructor(private _exampleDatabase: ExampleDatabase) { 
    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._filterChange, 
    ]; 

    return Observable.merge(...displayDataChanges).map(() => { 
     return this._exampleDatabase.data.slice().filter((item: UserData) => { 
     let searchStr = (item.name + item.color).toLowerCase(); 
     return searchStr.indexOf(this.filter.toLowerCase()) != -1; 
     }); 
    }); 
    } 

    disconnect() {} 
} 

排序列例如:

import {Component, ViewChild} from '@angular/core'; 
import {DataSource} from '@angular/cdk'; 
import {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'; 

@Component({ 
    selector: 'table-sorting-example', 
    styleUrls: ['table-sorting-example.css'], 
    templateUrl: 'table-sorting-example.html', 
}) 
export class TableSortingExample { 
    displayedColumns = ['userId', 'userName', 'progress', 'color']; 
    exampleDatabase = new ExampleDatabase(); 
    dataSource: ExampleDataSource | null; 

    @ViewChild(MdSort) sort: MdSort; 

    ngOnInit() { 
    this.dataSource = new ExampleDataSource(this.exampleDatabase, this.sort); 
    } 
} 

/** Constants used to fill up our data base. */ 
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']; 

export interface UserData { 
    id: string; 
    name: string; 
    progress: string; 
    color: string; 
} 

/** An example database that the data source uses to retrieve data for the table. */ 
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))] 
    }; 
    } 
} 

/** 
* Data source to provide what data should be rendered in the table. Note that the data source 
* can retrieve its data in any way. In this case, the data source is provided a reference 
* to a common data base, ExampleDatabase. It is not the data source's responsibility to manage 
* the underlying data. Instead, it only needs to take the data and send the table exactly what 
* should be rendered. 
*/ 
export class ExampleDataSource extends DataSource<any> { 
    constructor(private _exampleDatabase: ExampleDatabase, 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._sort.mdSortChange, 
    ]; 

    return Observable.merge(...displayDataChanges).map(() => { 
     return this.getSortedData(); 
    }); 
    } 

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

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

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

回答

1

一個實例已被添加to the docs和下一個版本之後會出現。

相關連接方法:

/** Connect function called by the table to retrieve one stream containing the data to render. */ 
connect(): Observable<UserData[]> { 
    // Listen for any changes in the base data, sorting, filtering, or pagination 
    const displayDataChanges = [ 
    this._exampleDatabase.dataChange, 
    this._sort.mdSortChange, 
    this._filterChange, 
    this._paginator.page, 
    ]; 

    return Observable.merge(...displayDataChanges).map(() => { 
    // Filter data 
    this.filteredData = this._exampleDatabase.data.slice().filter((item: UserData) => { 
     let searchStr = (item.name + item.color).toLowerCase(); 
     return searchStr.indexOf(this.filter.toLowerCase()) != -1; 
    }); 

    // Sort filtered data 
    const sortedData = this.sortData(this.filteredData.slice()); 

    // Grab the page's slice of the filtered sorted data. 
    const startIndex = this._paginator.pageIndex * this._paginator.pageSize; 
    this.renderedData = sortedData.splice(startIndex, this._paginator.pageSize); 
    return this.renderedData; 
    }); 
}