问题描述
我正在尝试使用DataSource接口通过服务器端分页来更新MatTableData.
I am trying to use the DataSource interface to update MatTableData, using server-side pagination.
<div>
<mat-table [dataSource]="dataSource" matSort matSortDisableClear>
<ng-container matColumnDef="type">
<mat-header-cell *matHeaderCellDef mat-sort-header class="w-200 th-center"> Type</mat-header-cell>
<mat-cell *matCellDef="let v" class="w-200 th-center"> {{v.type}} </mat-cell>
</ng-container>
<ng-container matColumnDef="title">
<mat-header-cell *matHeaderCellDef mat-sort-header class="w-200 th-center"> Title</mat-header-cell>
<mat-cell *matCellDef="let v" class="w-200 th-center"> {{v.title}} </mat-cell>
</ng-container>
<ng-container matColumnDef="status">
<mat-header-cell *matHeaderCellDef mat-sort-header class="w-200 th-center"> Status</mat-header-cell>
<mat-cell *matCellDef="let v" class="w-200 th-center"> {{v.status}} </mat-cell>
</ng-container>
<ng-container matColumnDef="url">
<mat-header-cell *matHeaderCellDef mat-sort-header class="w-200 th-center"> Url</mat-header-cell>
<mat-cell *matCellDef="let v" class="w-200 th-center"> {{v.url}} </mat-cell>
</ng-container>
<ng-container matColumnDef="host">
<mat-header-cell *matHeaderCellDef mat-sort-header class="w-250 th-center"> Host </mat-header-cell>
<mat-cell *matCellDef="let v" class="w-250 th-center"> {{v.host}} </mat-cell>
</ng-container>
<ng-container matColumnDef="ipv4">
<mat-header-cell *matHeaderCellDef mat-sort-header class="w-250 th-center"> Ipv4 </mat-header-cell>
<mat-cell *matCellDef="let v" class="w-250 th-center"> {{v.ipv4}} </mat-cell>
</ng-container>
<ng-container matColumnDef="category">
<mat-header-cell *matHeaderCellDef mat-sort-header class="w-250 th-center"> Category
</mat-header-cell>
<mat-cell *matCellDef="let v" class="w-250 th-center"> {{v.category}} </mat-cell>
</ng-container>
<ng-container matColumnDef="id">
<mat-cell *matCellDef="let v"> {{v.id}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="getDisplayedColumns()"></mat-header-row>
<mat-row class="element-row" *matRowDef="let row; columns: getDisplayedColumns();">
</mat-row>
</mat-table>
<mat-paginator [length]="total" [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]">
</mat-paginator>
</div>
@Component({
selector: 'kt-vulnerability-list',
templateUrl: './vulnerability-list.component.html',
styleUrls: ['./vulnerability-list.component.scss']
})
export class VulnerabilityListComponent implements OnInit, AfterViewInit, OnDestroy {
displayColumns;
dataSource: VulnerabilityDataSource
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
total = 1172;
constructor(private globalEntityStore: GlobalEntityStore,
private vulnerabilityDataService: VulnerabilityDataService,
private activatedRoute: ActivatedRoute) {
}
ngOnInit(): void {
// const store$ = this.globalEntityStore.state$;
const tableConfig = new VulnerabilityTableConfig();
this.displayColumns = tableConfig.configClient;
this.dataSource = new VulnerabilityDataSource(this.vulnerabilityDataService);
this.dataSource.loadVulns('ERA Home Security Ltd', '', 'asc', 0, 1);
}
ngAfterViewInit() {
this.sort.sortChange
.subscribe(() => this.paginator.pageIndex = 0);
merge(this.sort.sortChange, this.paginator.page)
.pipe(
untilDestroyed(this),
tap(() => this.loadVulnsPage()),
tap( () => {
this.total -= this.paginator.pageSize;
})
)
.subscribe();
}
loadVulnsPage() {
this.dataSource.loadVulns(
'ERA Home Security Ltd',
'',
'asc',
this.paginator.pageIndex,
this.paginator.pageSize);
}
getDisplayedColumns() {
return this.displayColumns
.filter(cd => !cd.hidden)
.map(cd => cd.name);
}
ngOnDestroy(): void {
}
export class VulnerabilityDataSource implements DataSource<Vulnerability> {
private vulnerabilitySubject = new BehaviorSubject<Vulnerability[]>([]);
private loadingSubject = new BehaviorSubject<boolean>(false);
public loading$ = this.loadingSubject.asObservable();
constructor(private vulnerabilityDataService: VulnerabilityDataService) {
this.vulnerabilitySubject.subscribe(res => console.log('vulnerability subject emiiting ', res))
}
public thing() {
return this.vulnerabilitySubject.asObservable()
}
connect(collectionViewer: CollectionViewer): Observable<Vulnerability[]> {
console.log('connect called');
return this.vulnerabilitySubject.asObservable();
}
disconnect(collectionViewer: CollectionViewer): void {
this.vulnerabilitySubject.complete();
}
loadVulns(clientName: string, filter = '',
sortDirection = 'asc', pageIndex = 0, pageSize = 3) {
this.vulnerabilityDataService.fetchVulnerabilities(clientName, filter, sortDirection,
pageIndex, pageSize)
.pipe(
catchError(() => of([])),
map(res => {
return new JsonConvert().deserializeArray(res, Vulnerability);
})
).subscribe(v => {
this.vulnerabilitySubject.next(v);
});
}
}
问题是 Connect()没有更新组件中的 dataSource .它确实渲染了2页,但表中未渲染第三页.
The problem is the Connect() is not updating dataSource in my component.It does render 2 pages, the third page is not rendered in the table.
我可以看到HTTP调用,并 this.vulnerabilitySubject.next(v); 发出下一组值.但是,connect方法由于某种原因而中断,并且不会在第2页之后更新表.
I can see the HTTP calls and this.vulnerabilitySubject.next(v); emitting the next set of values. However, the connect method breaks for some reason and does not update the table beyond after page 2.
任何人有什么想法吗?我似乎无法弄清楚这一点.
Any ideas from anyone? I can't seem to figure this one out.
推荐答案
您的VulnerabilityDataSource,没有属性 data
, filter
和 sort
...
Your VulnerabilityDataSource, has not property data
nor filter
nor sort
...
真的,我无法想象您想用您的代码实现什么.如果只有您想要在服务器中具有过滤器,排序和分页功能的mat-table,则只能订阅filter.valuesChange,paginator.page和sort.sortChange
Really I can't imagine what do you want to reach with your code. If the only you want a mat-table with filter, sort and pagination in server, you can get it only subscribing to filter.valuesChange, paginator.page and sort.sortChange
假设您有一项具有两种功能的服务
Imagine you has a service with two functions
//return and observable with the length of the data
getLength(filter:string)
//return an observable of an array with the data filtered, ordered and take account
//page and pageSize
getData(page:number,
pageSize:number,
filter:string,
sortField:string,
sortDirection:string)
在ngAfterViewInit中,您可以有一些类似的东西
In ngAfterViewInit you can has some like
ngAfterViewInit() {
const getLength = this.filter.valueChanges.pipe(
startWith(null),
debounceTime(200),
switchMap((res: string) => this.dataService.getLength(res)),
tap((res: number) => {
this.paginator.firstPage();
this.total = res;
})
);
const sort = this.sort.sortChange.pipe(
tap(() => this.paginator.firstPage())
);
merge(getLength, sort, this.paginator.page)
.pipe(
distinctUntilChanged(),
tap(_ => (this.isLoadingResults = true)),
switchMap(res => {
return this.dataService.getData(
this.paginator.pageIndex,
this.paginator.pageSize,
this.filter.value,
this.sort.active,
this.sort.direction
);
}),
tap(_ => (this.isLoadingResults = false))
)
.subscribe((res: any[]) => {
this.dataSource = res;
});
}
其中
filter = new FormControl();
isLoadingResults = false;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
看到我们合并了可观测的变量:当由"filter"组成的formControl出现时,更改值,更改分页器中的分页器以及对数据进行排序时
See that we merge trhee observables: when the formControl that make of "filter" change the value, when change the pagine in paginator and when sort the data
在后两种情况下,我们使用 pipe(tap)
发送到第一页.这是 stackblitz ,我希望这可以帮助您
We use pipe(tap)
to send to the first page in the last two cases. This is the stackblitz, I hope this can help you
这篇关于连接方法DataSource不会为MatTable发出所有分页的行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!