Angular MatPaginator not working

前端 未结 30 1567
情歌与酒
情歌与酒 2020-12-04 23:05

I have 2 components. Both have mat-table and paginators and pagination is working for one component and not working for the other component though the code is similar. Below

30条回答
  •  既然无缘
    2020-12-04 23:48

    This took me hours to finally track down and understand why my table wasn't working. Placing some console.logs() helped me figure out the order of events and why it didn't work consistently. My scenario was similar to the original issue above with a dynamic data source, but slightly different. For me, when I would first refresh my angular app, the paginator state would be set and then the data for my table would be set. When these events would happen in the this order the paginator worked just as expected.

    Because I was using ReplaySubjects for getting the data for my tables, my paginator state would be set in ngAfterViewInit and then the table data would come in from my subscription (it depends on user ID so I don't have an initial value and that is why I didn't use BehaviorSubjects). My problem was that, when I would navigate to another component in my app, and return to my dynamic table data source, the table data would be set before the paginator state. This would make the paginator show page x, but the displayed data would always be the first page of data.

    To fix this annoying issue I:

    1. Wrote a simple function for setting my table data as someone mentioned above:
      setTableData() {
        // set table data
        this.tableData.data = this.images.filter(img => this.filterData(img));
    
        // some other code below
        ....
      }
    
    1. Added two flags in my component, one for if I had loaded the table data and one for if my pagination state had been set. This way I could ensure that the pagination state is set before the data.
      // initialize our data source for our table and set flags for state
      tableData = new MatTableDataSource(this.images);
      loading = true;
      setPageState = false;
    
    1. Added a setTimeout to ngAfterViewInit which would set my paginator state and set my table data only if the table data came through before ngAfterViewInit was called. The setTimeout prevents the annoying "expression changed after value was checked" error.
      ngAfterViewInit() {
        // add pagination state to our table
        setTimeout(() => {
          console.log('Set paginator state');
          this.setPageState = true;
          this.paginator.pageIndex = this.state.pageIndex;
    
          // check if we are not loading data, meaning the table came in first so
          // we need to set the data here
          if (!this.loading) {
            this.setTableData();
          }
        }, 0);
      }
    
    1. Lastly, in ngOnInit, where I subscribe to my data, I do not set my table data unless the paginator state was set first:
      ngOnInit() {
        console.log('ngOnInit');
        this.tableData.sort = this.sort;
        this.tableData.paginator = this.paginator;
    
        // listen for data
        this.dbService.images.subscribe(images => {
          console.log('Data subscription');
          // save images
          this.images = images;
    
          // only set table data if paginator state has been set, otherwise it doesnt work
          if (this.setPageState) {
            this.setTableData();
          }
    
          // hide spinner and update that we have data
          this.loading = false;
        });
    
        // other code
        .....
      }
    

    And with that, my pagination was finally working consistently for when I first login to the app and when I navigate to other pages and go back to my dynamic table.

提交回复
热议问题