类通过过滤扩展MatTableDataSource和表

时间:2018-10-05 09:12:12

标签: angular rxjs angular-material2 angular-material-6 angular-cdk

这是我的业余爱好项目,并且由于此问题而停滞了一段时间。这可能是一个简单的问题,但是我对Angular和JS的了解非常有限。尽管如此,我的代码仍在下面(我将其缩短了一点),并且在一定程度上可以正常工作。它正在从服务器获取数据,然后显示在客户端。那里没有问题,但是现在当我尝试进行客户端过滤时,什么也没发生。从字面上看。我正在输入过滤器输入框,什么也没有。表行未过滤。

我想知道两件事:

  1. 我是否使用正确的方法(可以扩展MatTableDataSource)吗?
  2. 我做错了什么(如果我可以扩展MatTableDataSource)?

MyData.ts

export interface MyData {
    id: number;
    description: string;
}

MyData.service.ts

export class MyService {

    constructor(private http: HttpClient) { }

    getData(): Observable<MyData[]> {
        return this.http.get...
    }
}

MyData.datasource.ts

export class MyDataSource extends MatTableDataSource<MyData> {

    private mySubject = new BehaviorSubject<MyData[]>([]);

    constructor(private myService: MyService) { super(); }

    loadData() {
        this.myService.getData()
        .pipe(catchError(() => of([])))
        .subscribe(data => this.mySubject.next(data));
    }

    connect(): BehaviorSubject<myData[]> {
        return this.mySubject;
    }

    disconnect(): void {
        this.mySubject.complete();
    }
}

MyData.component.ts

export class MyDataComponent implements OnInit {

    displayedColumns= ["id", "description"];
    dataSource: MyDataSource;

    constructor(private myService: MyService) { }

    ngOnInit() {
        this.dataSource = new MyDataSource(this.myService);
        this.dataSource.loadData();
    }

        applyFilter(filterValue: string) {
            this.dataSource.filter = filterValue.trim().toLowerCase();
        }
}

MyData.component.html

<mat-form-field>
    <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>

<mat-table [dataSource]="dataSource">

    <ng-container matColumnDef="id">
        <mat-header-cell *matHeaderCellDef>ID</mat-header-cell>
        <mat-cell *matCellDef="let data">{{data.id}}</mat-cell>
    </ng-container>

    <ng-container matColumnDef="description">
        <mat-header-cell *matHeaderCellDef>Description</mat-header-cell>
        <mat-cell *matCellDef="let data">{{data.description}}</mat-cell>
    </ng-container>

</mat-table>

1 个答案:

答案 0 :(得分:0)

是的,如果您想对数据进行更多控制,例如自定义排序,过滤,分页和实时数据流/处理,则可以扩展数据源。如果没有,您可以使用材料网站中提供的默认数据源类

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

如上面的材料站点所述,如果您想做更复杂的事情,则可以扩展数据源类

Advanced data sources
The simplest way to provide data to your table is by passing a data array. More complex use-cases may benefit from a more flexible approach involving an Observable stream or by encapsulating your data source logic into a DataSource class.

这是一个有关如何使用它的更复杂的示例。

以下代码是数据源的构造函数。它接受了分页器,数据服务和Mat排序。

  constructor(public _dataService: DataService,
              public _paginator: MatPaginator,
              public _sort: MatSort) {
    super();
    // Reset to the first page when the user changes the filter.
    this._filterChange.subscribe(() => this._paginator.pageIndex = 0);
  }

然后,您将实现connect类。此连接类是可观察的,您的mat-table将订阅该可观察的对象,并根据可观察的返回结果显示数据

  connect(): Observable<Array<Data>> {
    // Listen for any changes in the base data, sorting, filtering, or 
    //pagination the below object types are all observable/behaviour 
    //subjects
    const displayDataChanges = [
      this._dataService.entryDataChange,
      this._sort.sortChange,
      this._filterChange,
      this._paginator.page
    ]; 
    data: YourCurrentData;
    // Merge all the observable into one stream
    return Observable.merge(...displayDataChanges).map((n) => {
      // If is filter data observer do action
      // If is a sort observer emitting data do action
      // If is new incoming data do action
      // If is a paginator observable emmiting data do action
      // Return filtered, sorted, and paged data that you want to display
      // on your current page. 
    });
  }

以上示例使用旧的rxjs版本。但是希望您能理解其中的逻辑!