微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

连接方法DataSource不会为MatTable发出所有分页的行

如何解决连接方法DataSource不会为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',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',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页之后的表。

任何人有什么想法吗?我似乎无法弄清楚这一点。

解决方法

您的VulnerabilityDataSource,没有属性datafiltersort ...

真的,我无法想象您想用代码实现什么。如果只有您想要在服务器中具有过滤器,排序和分页功能的席子表,则只能订阅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可观察对象:当由“过滤器”组成的formControl更改值时,何时在分页器中更改分页器以及何时对数据进行排序

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。