连接方法DataSource不会为MatTable发出所有分页的行 [英] Connect method DataSource is not emitting all paginated rows for MatTable

查看:75
本文介绍了连接方法DataSource不会为MatTable发出所有分页的行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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发出所有分页的行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆