Multiple material pagination in one component doesn't work in Angular

22,978

Solution 1

For mutiple MatPaginator and MatSort components present in single page you need yo use

@ViewChildren(MatPaginator) paginator = new QueryList<MatPaginator>();
@ViewChildren(MatSort) sort = new QueryList<MatSort>();

in your code which will return you list of MatSort and MatPaginator defined in the order in which it is present int your page. Below is the complete implemetation

import { Component, OnInit, ViewChild, ViewChildren, AfterViewInit, QueryList } from '@angular/core';
import { MatTableDataSource, MatSort, MatPaginator } from '@angular/material';

export interface AssignmentElement {
  assignmentId: number;
  action: string;
  userName: string;
  roleName: string;
  enabled: string;
  createdOn: string;
  createdBy: string;
  modifiedOn: string;
  modifiedBy: string;
  status: string;
}

export interface RoleElement {
  roleId: number;
  action: string;
  roleName: string;
  roleDescription: string;
  createdOn: string;
  createdBy: string;
  modifiedOn: string;
  modifiedBy: string;
  status: string;
}

export const ASSIGNMENT_ELEMENT_DATA: AssignmentElement[] = [
  { assignmentId: 1, action: 'Grant', userName: 'Dummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 2, action: 'Grant', userName: 'Dummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 3, action: 'Grant', userName: 'ADummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 4, action: 'Grant', userName: 'Dummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 8, action: 'Grant', userName: 'BDummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 1, action: 'Grant', userName: 'Dummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 12, action: 'Grant', userName: 'ZDummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 12, action: 'Grant', userName: 'Dummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 19, action: 'Grant', userName: 'Dummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 111, action: 'Grant', userName: 'PDummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 122, action: 'Grant', userName: 'Dummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { assignmentId: 133, action: 'Grant', userName: 'QDummy', roleName: 'admin', enabled: 'Y', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' }

];

export const ROLE_ELEMENT_DATA: RoleElement[] = [
  { roleId: 1, action: 'Create', roleName: 'admin', roleDescription: 'This is test role', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { roleId: 3, action: 'Create', roleName: 'cadmin', roleDescription: 'This is test role', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { roleId: 1, action: 'Create', roleName: 'admin', roleDescription: 'This is test role', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { roleId: 5, action: 'Create', roleName: 'vadmin', roleDescription: 'This is test role', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { roleId: 4, action: 'Create', roleName: 'zadmin', roleDescription: 'This is test role', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' },
  { roleId: 1, action: 'Create', roleName: 'admin', roleDescription: 'This is test role', createdOn: '21-Feb-2018', createdBy: 'Dummy', modifiedOn: '', modifiedBy: '', status: 'PENDING' }
];

@Component({
  selector: 'app-myqueue',
  templateUrl: './myqueue.component.html',
  styleUrls: ['./myqueue.component.css']
})
export class MyqueueComponent implements OnInit, AfterViewInit {

  dataSource1: MatTableDataSource<AssignmentElement>;
  dataSource2: MatTableDataSource<RoleElement>;
  @ViewChildren(MatPaginator) paginator = new QueryList<MatPaginator>();
  @ViewChildren(MatSort) sort = new QueryList<MatSort>();

  assignmentColumn: string[] = [
    'select', 'assignmentId', 'action', 'userName', 'roleName', 'enabled', 'createdOn', 'createdBy', 'modifiedOn', 'modifiedBy', 'status'
  ];
  roleColumn: string[] = [
    'select', 'roleId', 'action', 'roleName', 'roleDescription', 'createdOn', 'createdBy', 'modifiedOn', 'modifiedBy', 'status'
  ];

  constructor() {
    this.dataSource1 = new MatTableDataSource<AssignmentElement>(ASSIGNMENT_ELEMENT_DATA);
    this.dataSource2 = new MatTableDataSource<RoleElement>(ROLE_ELEMENT_DATA);
  }

  ngOnInit() {
  }

  ngAfterViewInit() {
    this.dataSource1.paginator = this.paginator.toArray()[0];
    this.dataSource1.sort = this.sort.toArray()[0];
    this.dataSource2.paginator = this.paginator.toArray()[1];
    this.dataSource2.sort = this.sort.toArray()[1];
  }

}

Solution 2

You can retrieve them by #id also:

In your HTML:

<mat-paginator #categoryPaginator [pageSizeOptions]="[15]" hidePageSize="true" showFirstLastButtons="false"></mat-paginator>

In your component TS:

@ViewChild('categoryPaginator', { read: MatPaginator }) categoryPaginator: MatPaginator;

EDIT

After seeing gh0st's comment I did some digging and it seems the "read" option is supposed to be a boolean ViewChild angular documentation so I did an experiment and { read: true } does not work - but {read: false} does - but given false is the default removing it altogether still works - so it seems this is the most succinct way to do this is:

@ViewChild('categoryPaginator') categoryPaginator: MatPaginator;

I have tested this with 3 tables/paginators in the one view component and they appear to still work as expected.

I can only assume that { read: MatPaginator } is actually being interpreted as { read: false }

The Angular documentation does actually give a rough example of this:

A template reference variable as a string (e.g. query <my-component #cmp></my-component> with @ViewChild('cmp'))

EDIT-2

I encountered a scenario where I have two material autocompletes in one component and need to access the MatAutoComplete trigger for one of them - it seems in this instance the { read: MatAutocompleteTrigger } is essential otherwise it just returns an ElementRef:

@ViewChild('localityAutoComplete', { read: MatAutocompleteTrigger }) trigger: MatAutocompleteTrigger;
Share:
22,978
Sithys
Author by

Sithys

https://www.poolarino.de

Updated on July 09, 2022

Comments

  • Sithys
    Sithys almost 2 years

    I try to create a component which includes two dataTables each of it with another dataSource. My Tables aren't visible right after the component is loaded because of my *ngIf so that i couldn't use ngAfterViewInit() instead i'm using a solution a user pointed out on Github:

      private paginator: MatPaginator;
      private reportingPaginator: MatPaginator;
      private sort: MatSort;
      private reportingSort: MatSort;
    
      @ViewChild(MatSort) set matSort(ms: MatSort) {
        this.sort = ms;
        this.reportingSort = ms;
        this.setDataSourceAttributes();
      }
    
      @ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
        this.paginator = mp;
        this.reportingPaginator = mp;
        this.setDataSourceAttributes();
      }
    
      setDataSourceAttributes() {
    
          this.dataSource.paginator = this.paginator;
          this.dataSource.sort = this.sort;
    
          this.reportingDataSource.paginator = this.reportingPaginator;
          this.reportingDataSource.sort = this.reportingSort;
    
    }
    

    But i still can't get it to work. My Pagination doesn't work, when both paginators are included into the @ViewChild(MatPaginator). If i only include one of the paginators

    @ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
        this.reportingPaginator = mp;
        this.setDataSourceAttributes();
    }
    

    or

    @ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
        this.paginator = mp;
        this.setDataSourceAttributes();
    }
    

    the one i included works fine! So what do i need to do to get both paginators work?