Home:ALL Converter>Unable to get Angular Material2 Table sort and paginator to work

Unable to get Angular Material2 Table sort and paginator to work

Ask Time:2018-02-27T18:33:17         Author:tatsu

Json Formatter

I've been trying to implement both sort and paginator on my Material table with little success.

the following gives me my table but when I click on the header no sorting happens and the whole datatset is listed despite paginator indicating there should only be 10 results also when I click paginator buttons it's own state changes but the dataset is not updated to follow suit :

import {
  AfterViewInit, Component, Input, OnChanges, OnInit, SimpleChanges,
  ViewChild
} from '@angular/core';
import {MatSort, MatPaginator, MatTableDataSource} from '@angular/material';
import {SelectionModel} from '@angular/cdk/collections';
import {ApiConnectService} from '../../../../../assets/services/api.connect.service';

@Component({
  selector: 'app-review-table',
  templateUrl: './review.table.component.html',
  styleUrls: ['./review.table.component.scss']
})
export class ReviewTable implements OnInit, AfterViewInit, OnChanges {

  @Input() purchaseOrders: Array<object>;
  @Input() searchKey: string;
  @ViewChild(MatSort) sort: MatSort;
  @ViewChild(MatPaginator) paginator: MatPaginator;
  dataSource: MatTableDataSource<any>;
  selection = new SelectionModel<any>(true, null);
  displayedColumns = ['rowcount', 'siteId', 'importDate', 'poPoNumber', 'poPrice'];

  constructor(private _api: ApiConnectService) { }

  ngOnInit() {
    this._api.getPurchaseOrders()
      .subscribe(data => {
        this.dataSource = new MatTableDataSource(data);
      }, err => {
        console.log(err);
      });
  }

  ngOnChanges(changes: SimpleChanges) {
    for (let property in changes) {
      if (changes[property].previousValue !== changes[property].currentValue){
        if (property === 'searchKey') {
          this.applyFilter(this.searchKey);
        }
      }
    }
  }

  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  applyFilter(filterValue: string) {
    filterValue = filterValue.trim();
    filterValue = filterValue.toLowerCase();
    this.dataSource.filter = filterValue;
  }
}

In this second implementation I put only the sorting code and set the value for the dataset within my subscription to my observable also I added @ViewChild(MatSort) a second time in front of the dataset declaration. This weird experimentation that is against what the guide https://material2-docs-dev.firebaseapp.com/components/table/examples stipulates resulted in the sorting working as intended :

import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { ApiConnectService } from '../../../../assets/services/api.connect.service';
import { MatSort, MatTableDataSource } from '@angular/material';
import { SelectionModel } from '@angular/cdk/collections';


@Component({
  selector: 'app-menu3',
  templateUrl: './purchase.orders.component.html',
  styleUrls: ['./purchase.orders.component.scss']
})
export class PurchaseOrders implements OnInit, AfterViewInit {

  @ViewChild(MatSort) sort: MatSort;
  @ViewChild(MatSort) dataSource: MatTableDataSource<any>;
  multipleSelect = true;
  selection = new SelectionModel<any>(this.multipleSelect, null);

  displayedColumns = ['siteId', 'importDate', 'poPoNumber', 'poPrice'];

  constructor(private _api: ApiConnectService) {
  }

  ngOnInit() {
    this._api.getPurchaseOrders()
      .subscribe(data => {
        this.dataSource = new MatTableDataSource(data);
      }, err => {
        console.log(err);
      });
  }

  ngAfterViewInit() {
    this.dataSource.sort = this.sort;
  }

  applyFilter(filterValue: string) {
    filterValue = filterValue.trim();
    filterValue = filterValue.toLowerCase();
    this.dataSource.filter = filterValue;
  }
}

The issue is that I get this browser-console error which result in my browser animations getting sent to the wrong element -> my dataset. The error talks about the data source being of the wrong type (I guess?) but then the table is displayed anyways and functions :

core.js:1448 ERROR Error: Provided data source did not match an array, Observable, or DataSource
    at getTableUnknownDataSourceError (table.es5.js:379)
    at MatTable.CdkTable._observeRenderChanges (table.es5.js:860)
    at MatTable.CdkTable.ngAfterContentChecked (table.es5.js:577)
    at callProviderLifecycles (core.js:12702)
    at callElementProvidersLifecycles (core.js:12673)
    at callLifecycleHooksChildrenFirst (core.js:12656)
    at checkAndUpdateView (core.js:13806)
    at callViewAction (core.js:14153)
    at execComponentViewsAction (core.js:14085)
    at checkAndUpdateView (core.js:13808)

In short this is no solution.

I tried doubling down on my little hack with @ViewChild(MatSort) @ViewChild(MatPaginator) dataSource: MatTableDataSource<any>; but that grooved fruitless. it just ignores the MatPaginator part. the paginator is still unlinked.

Is the component where the table is declared obligated to be the same where the API call for your data is made or are you allowed to make the data call in a parent and pass it to the table via @Input ?

what am I missing for Column-Sort and Pagination to work in this latter case where I am placing the table as a child to the component that retrieves that data?

why am I getting this error when I force Sort to work?

Author:tatsu,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/49006540/unable-to-get-angular-material2-table-sort-and-paginator-to-work
yy