简体   繁体   English

无法使Angular Material2表排序和分页器正常工作

[英]Unable to get Angular Material2 Table sort and paginator to work

I've been trying to implement both sort and paginator on my Material table with little success. 我一直试图在我的Material表上同时实现sort和paginator,但收效甚微。

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 : 以下是我的表格,但是当我单击页眉时,没有排序,并且尽管分页器指示了整个数据集,但仍列出了整个数据集,当我单击分页器按钮时,它也应该具有10个结果,但其自身的状态发生了变化,但是数据集没有更新以适应:

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. 在第二个实现中,我仅放置排序代码,并将订阅中的数据集的值设置为我的可观察对象,并且我第二次在数据集声明之前添加了@ViewChild(MatSort) 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 : 这项与https://material2-docs-dev.firebaseapp.com/components/table/examples指南所规定的相反的怪异实验导致排序工作按预期进行:

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>; 我尝试使用@ViewChild(MatSort) @ViewChild(MatPaginator) dataSource: MatTableDataSource<any>;我的小技巧加倍@ViewChild(MatSort) @ViewChild(MatPaginator) dataSource: MatTableDataSource<any>; but that grooved fruitless. 但是那没有结果。 it just ignores the MatPaginator part. 它只是忽略了MatPaginator部分。 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 ? 声明表的组件是否必须与进行数据的API调用的组件相同,或者是否允许在父级中进行数据调用并通过@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? 强制排序工作时为什么会出现此错误?

You create the MatTableDataSource after receiving some asynchronous data. 您收到一些异步数据后,创建MatTableDataSource。 So certainly that when you do 所以可以肯定的是

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

this.dataSource might be null this.dataSource可能为null

Can you change 你能改变吗

constructor(private _api: ApiConnectService) { }

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

to

  constructor(private _api: ApiConnectService) {
      this.dataSource = new MatTableDataSource(data); // create MatTableDataSource (synchronous) here to allow sort / filtering binding
  }

  ngOnInit() {
    this._api.getPurchaseOrders()
      .subscribe(data => {
        this.dataSource.data = data; // populate data here 
      }, err => {
        console.log(err);
      });
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM