【问题标题】:Connect method DataSource is not emitting all paginated rows for MatTableConnect 方法 DataSource 未发出 MatTable 的所有分页行
【发布时间】:2020-09-07 15:10:00
【问题描述】:

我正在尝试使用 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 个页面,第三个页面没有呈现在表格中。

我可以看到 HTTP 调用和 this.vulnerabilitySubject.next(v); 发出下一组值。但是,connect 方法由于某种原因中断,并且在第 2 页之后不会更新表。

任何人的任何想法?这个我好像搞不懂。

【问题讨论】:

    标签: angular angular-material2


    【解决方案1】:

    您的 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;
    

    看到我们合并了三个可观察对象:当构成“过滤器”的formControl改变值时,当改变分页器中的分页时,当对数据进行排序时

    在最后两种情况下,我们使用pipe(tap) 发送到第一页。我是the stackblitz,希望对你有帮助

    【讨论】:

    • 这太棒了!非常感谢。我将尝试实现这一点。
    猜你喜欢
    • 2012-09-17
    • 2014-11-11
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    相关资源
    最近更新 更多