Cod*_*mpy 5 javascript rxjs angular-material angular
我使用此命令创建了一个角度材质数据表ng generate @angular/material:material-table,它提供了以下文件结构:
这里的想法是在table-datasource.ts. 默认情况下,数据放置在内部的 Array 中,table-datasource.ts但在我的例子中,它来自 ngxs-store,它公开了Array 的 Observable。Atm 我有以下实现:
表数据源.ts:
export class TokenTableDataSource extends DataSource<TokenTableItem> {
@Select(TokenTableState.getTokenTableItems) private tokenTableItems$:Observable<TokenTableItem[]>;
totalItems$ = new BehaviorSubject<TokenTableItem[]>([]);
constructor(private paginator: MatPaginator, private sort: MatSort) {
super();
}
/**
* Connect this data source to the table. The table will only update when
* the returned stream emits new items.
* @returns A stream of the items to be rendered.
*/
connect(): Observable<TokenTableItem[]> {
this.tokenTableItems$.subscribe(item => this.totalItems$.next(item));
// init on first connect
if (this.totalItems$.value === undefined) {
this.totalItems$.next([]);
this.paginator.length = this.totalItems$.value.length;
}
// Combine everything that affects the rendered data into one update
// stream for the data-table to consume.
const dataMutations = [
observableOf(this.totalItems$),
this.paginator.page,
this.sort.sortChange
];
return merge(...dataMutations).pipe(
map(() => this.totalItems$.next(this.getPagedData(this.getSortedData([...this.totalItems$.value])))),
mergeMap(() => this.totalItems$)
);
}
...generated paging and sorting methods
Run Code Online (Sandbox Code Playgroud)
表组件.html:
<div class="mat-elevation-z8">
<table mat-table class="full-width-table" [dataSource]="dataSource" matSort aria-label="Elements">
...multiple columns
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator #paginator
[length]="this.dataSource.totalItems$.value?.length"
[pageIndex]="pageIndex"
[pageSize]="pageSize"
[pageSizeOptions]="pageSizeOptions"
[showFirstLastButtons]=true
(page)="handlePage($event)">
</mat-paginator>
</div>
Run Code Online (Sandbox Code Playgroud)
表.组件.ts:
export class TokenTableComponent implements OnInit {
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
dataSource: TokenTableDataSource;
pageSizeOptions = [5, 10, 20, 40];
pageSize = this.pageSizeOptions[0];
pageIndex = 0;
tableLength = 0;
... colums definition
ngOnInit(): void {
this.dataSource = new TokenTableDataSource(this.paginator, this.sort);
}
public handlePage(pageEvent: PageEvent) {
// do what?
}
}
Run Code Online (Sandbox Code Playgroud)
什么在起作用:
什么不起作用:
pageSize将采用当前选定的内容并呈现此数量的行。对我来说奇怪的是,这只适用于降序(给定pageSize为 10,我选择 5,它会产生 5 行,但一旦选择 5,就不可能再次显示多于 5 的行)要求:
TableDataSource.connect()在组件中完成获取的解决方案。此外,这没有实现排序。 handlePage()方法中。 版本:
我想出了如何根据我的要求设置表格。主要的变化是我删除了从TableDataSource获取数据的 Observable并引入了DataService:
export class DataService {
//the @Select is from ngxs but can be anything returning an Observable
@Select(TokenTableState.getTokenTableItems) private tokenTableItems$: Observable<TokenTableViewItem[]>;
private initValue$: BehaviorSubject<TokenTableViewItem[]> = new BehaviorSubject<TokenTableViewItem[]>([]);
getAllItems(): Observable<TokenTableViewItem[]> {
const sources = [this.tokenTableItems$, this.initValue$];
return merge(...sources);
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,该服务从任何 Observable 输入获取数据,并将其与初始值合并到getAllItems方法中。
该组件有一个该服务的实例:
private _dataService: DataService | null;
它在 load 方法中将其移交给TableDatasource :
private loadData(): any {
this._dataService = new DataService();
this.dataSource = new TokenTableDataSource(
this._dataService,
this.paginator,
this.sort
);
fromEvent(this.filter.nativeElement, 'keyup').subscribe(() => {
if (!this.dataSource) {
return;
}
this.dataSource.filter = this.filter.nativeElement.value;
});
}
Run Code Online (Sandbox Code Playgroud)
我在TableDataSource中没有引用 DataService 的原因是组件中的分页器需要表格的长度进行渲染(如下所示)。
TableDataSource像这样使用DataService :
在connect方法中,它保存一个包含可能的数据突变的数组:
const dataMutations = [
this._dataChange,
this._sort.sortChange,
this._filterChange,
this._paginator.page
];
Run Code Online (Sandbox Code Playgroud)数组的_dataChange成员通过订阅DataService的getAllItems方法来获取它的值:
this._internalService.getAllItems().subscribe(data => {
this._dataChange.next(data);
});
Run Code Online (Sandbox Code Playgroud)dataMutations像这样使用来过滤、排序和返回应显示的数据:
return merge(...dataMutations).pipe(
map(() => {
// Filter data
this.filteredData = this._dataChange.value
.slice()
.filter((item: TokenTableViewItem) => {
const searchStr = (item.symbol + item.name).toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
// Sort filtered data
const sortedData = this.getSortedData(this.filteredData.slice());
// Grab the page's slice of the filtered sorted data.
this.renderedData = this.getPagedData(sortedData);
return this.renderedData;
})
);
Run Code Online (Sandbox Code Playgroud)filterChange在本地实例中定义
_filterChange = new BehaviorSubject('');
而分页和排序是通过构造函数从外部触发的
constructor(
public _internalService: DataService,
public _paginator: MatPaginator,
public _sort: MatSort
) {
super();
this._filterChange.subscribe(() => (this._paginator.pageIndex = 0));
}
Run Code Online (Sandbox Code Playgroud)
我还找到了在component.html中定义的分页解决方案,如下所示:
<mat-paginator #paginator
[length]="dataSource.filteredData.length"
[pageIndex]="pageIndex"
[pageSize]="pageSize"
[pageSizeOptions]="pageSizeOptions"
[showFirstLastButtons]=true>
</mat-paginator>
Run Code Online (Sandbox Code Playgroud)
并在component.ts中设置变量:
pageSizeOptions = [5, 10, 20, 40];
pageSize = this.pageSizeOptions[0];
pageIndex = 0;
Run Code Online (Sandbox Code Playgroud)
完整的代码可以在这个项目中看到,并且在Whatsmytoken.com上使用了该表的实时版本。