Connect 方法 DataSource 没有发出 MatTable 的所有分页行
Connect method DataSource is not emitting all paginated rows for MatTable
我正在尝试使用 DataSource 接口更新 MatTableData,使用服务器端分页。
<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 个页面,第三个页面没有在 table.
中渲染
我可以看到 HTTP 调用和 this.vulnerabilitySubject.next(v); 发出下一组值。但是,connect 方法由于某种原因中断并且不会更新第 2 页之后的 table。
任何人有什么想法吗?我似乎无法弄清楚这一点。
您的 VulnerabilityDataSource 没有 属性 data
也没有 filter
也没有 sort
...
我真的无法想象你想用你的代码达到什么目的。如果你只想要 mat-table 在服务器中进行过滤、排序和分页,你可以只订阅 filter.valuesChange、paginator.page 和 sort.sortChange
假设您有一个具有两个功能的服务
//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 中你可以有一些像
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;
看到我们合并了 trhee observables:当由“filter”组成的 formControl 更改值时,当更改分页器中的分页时以及对数据排序时
后两种情况我们使用pipe(tap)
发送到第一页。我是the stackblitz,希望对您有所帮助
我正在尝试使用 DataSource 接口更新 MatTableData,使用服务器端分页。
<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 个页面,第三个页面没有在 table.
中渲染我可以看到 HTTP 调用和 this.vulnerabilitySubject.next(v); 发出下一组值。但是,connect 方法由于某种原因中断并且不会更新第 2 页之后的 table。
任何人有什么想法吗?我似乎无法弄清楚这一点。
您的 VulnerabilityDataSource 没有 属性 data
也没有 filter
也没有 sort
...
我真的无法想象你想用你的代码达到什么目的。如果你只想要 mat-table 在服务器中进行过滤、排序和分页,你可以只订阅 filter.valuesChange、paginator.page 和 sort.sortChange
假设您有一个具有两个功能的服务
//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 中你可以有一些像
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;
看到我们合并了 trhee observables:当由“filter”组成的 formControl 更改值时,当更改分页器中的分页时以及对数据排序时
后两种情况我们使用pipe(tap)
发送到第一页。我是the stackblitz,希望对您有所帮助