Angular Material文档提供了一个很好的示例,说明如何向表(Table Selection docs)中添加选择。他们甚至提供Stackblitz进行试用。
我在code for the SelectionModel constructor中发现,第一个参数是是否可以进行多个选择(真)或(假)。第二个参数是最初选择的值的数组。
在演示中,它们没有任何初始选择的值,因此其构造函数(第36行)中的第二个参数是一个空数组(phone
|7799423934|
|9331224595|
|8981251522|
|7271767899|
)。
我想更改它,以便有一个初始选择的值,所以我将第36行更改为:
[]
这会将标题中的复选框更改为不确定状态(如预期的那样),但不会导致表中的行被选中。我是错误地设置了初始值,还是在这里遗漏了什么?如何设置初始选择的值?
答案 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]);
}
});
}