Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
541 views
in Technique[技术] by (71.8m points)

angular - Connect method DataSource is not emitting all paginated rows for MatTable

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);
    });

  }
}

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.

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your VulnerabilityDataSource, has not property data nor filter nor sort...

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)

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;
      });
  }

where

  filter = new FormControl();
  isLoadingResults = false;
  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

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

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...