如何为Angular Material Table SelectionModel添加初始选择?

时间:2018-09-04 20:37:13

标签: angular-material

Angular Material文档提供了一个很好的示例,说明如何向表(Table Selection docs)中添加选择。他们甚至提供Stackblitz进行试用。

我在code for the SelectionModel constructor中发现,第一个参数是是否可以进行多个选择(真)或(假)。第二个参数是最初选择的值的数组。

在演示中,它们没有任何初始选择的值,因此其构造函数(第36行)中的第二个参数是一个空数组(phone |7799423934| |9331224595| |8981251522| |7271767899| )。

我想更改它,以便有一个初始选择的值,所以我将第36行更改为:

[]

这会将标题中的复选框更改为不确定状态(如预期的那样),但不会导致表中的行被选中。我是错误地设置了初始值,还是在这里遗漏了什么?如何设置初始选择的值?

5 个答案:

答案 0 :(得分:3)

棘手的人。您需要通过以下方式初始化选择:从数据源输入中提取特定的PeriodicElement对象,然后将其传递给构造函数。

在这种情况下,您可以进行编码

selection = new SelectionModel<PeriodicElement>(true, [this.dataSource.data[1]);

这是因为SelectionModel检查活动选择的方式。

在表格标记中,您拥有

<mat-checkbox ... [checked]="selection.isSelected(row)"></mat-checkbox>

您希望此绑定将相应的行标记为已选中。但是方法isSelected(row)不会将此处传递的对象识别为选中对象,因为这不是您的选择在其构造函数中收到的对象。

“行”指向实际MatTableDataSource输入中的对象:

dataSource = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);

但是选择初始化:

selection = new SelectionModel<PeriodicElement>(true, [{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}]);

会随即随即创建一个新对象。您的选择会将此对象记住为所选对象。

当angular评估标记中的绑定时,SelectionModel在内部检查对象身份。将在内部所选对象集中寻找“行”指向的对象。

SelectionModel源代码中的第99-101行和第16行比较:

isSelected(value: T): boolean {
  return this._selection.has(value);
}

private _selection = new Set<T>();

答案 1 :(得分:0)

如果您执行以下操作,它也会起作用

selection = new SelectionModel<PeriodicElement>(true, [ELEMENT_DATA[1]])

要选择所有可以做的事情

selection = new SelectionModel<PeriodicElement>(true, [...ELEMENT_DATA])

我希望答案会有所帮助

答案 2 :(得分:0)

或者,如果您有一组值并且想要在之前进行过滤,则可以更动态:

selection = new SelectionModel<PeriodicElement>(true, [
...this.dataSource.data.filter(row => row.weight >= 4.0026)
]);

答案 3 :(得分:0)

我遇到了同样的问题,我使用dataSource在ngOnInit()中手动设置了初始值

ngOnInit() {
    this.dataSource.data.forEach(row => {
      if (row.symbol == "H") this.selection.select(row);
    });
  }

答案 4 :(得分:0)

如果您从 api 异步加载数据,这会变得更加棘手。这是我如何做到的: 首先,我从“@angular/cdk/table”实现了数据源。我还有一个 RxJS 主题,它在加载数据时触发(第一次或用户在分页部分更改页面时)

export abstract class BaseTableDataSource<T> implements DataSource<T>{
    private dataSubject = new BehaviorSubject<T[]>([]);
    private loadingSubject = new BehaviorSubject<boolean>(false);
    private totalRecordsSubject = new BehaviorSubject<number>(null);

    public loading$ = this.loadingSubject.asObservable();
    public dataLoaded$ = this.dataSubject.asObservable();
    public totalRecords$ = this.totalRecordsSubject.asObservable().pipe(filter(v => v != null));
    
    constructor(){}

    connect(collectionViewer: CollectionViewer): Observable<T[]>{
        return this.dataSubject.asObservable();
    }

    disconnect(collectionViewer: CollectionViewer): void {
        this.dataSubject.complete();
        this.loadingSubject.complete();
        this.totalRecordsSubject.complete();
    }
    
    abstract fetchData(pageIndex, pageSize, ...params:any[]) : Observable<TableData<T>>;
    abstract columnMetadata(): {[colName: string]: ColMetadataDescriptor };

    loadData(pageIndex, pageSize, params?:any[]): void{
        this.loadingSubject.next(true);

        this.fetchData(pageIndex, pageSize, params).pipe(
            finalize(() => this.loadingSubject.next(false))
        )
        .subscribe(data => {
            this.totalRecordsSubject.next(data.totalNumberOfRecords);
            this.dataSubject.next(data.records)
        });
    }

}

现在,当我想预选一行时,我可以在我的组件中编写这样的函数,该组件托管一个使用上述数据源实现的表

  selectRow(rowSelectionFn: (key: string) => boolean){
    this.dataSource.dataLoaded$.pipe(takeUntil(this.destroyed$))
    .subscribe(data => {
      const foundRecord = data.filter(rec => rowSelectionFn(rec));
      if(foundRecord && foundRecord.length >= 0){
        this.selection.toggle(foundRecord[0]);
      }
    });
  }