Angular MatPaginator无法正常工作

时间:2018-02-14 11:21:12

标签: angular pagination angular-material

我有2个组件。两者都有mat-table和paginator,并且分页对一个组件起作用,而不是为另一个组件工作,尽管代码类似。以下是我的HTML:

document.getElementById("info-win-1").innerHTML = testInfo

以下是我在component.ts中的代码:

<div class="mat-elevation-z8">

    <mat-table [dataSource]="dataSource" matSort>

      <ng-container matColumnDef="col1">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column1 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col1}} </mat-cell>
      </ng-container>

      <ng-container matColumnDef="col2">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column2 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col2}} </mat-cell>
      </ng-container>

      <!-- Different columns goes here -->

      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;">
      </mat-row>
    </mat-table>

    <mat-paginator #scheduledOrdersPaginator [pageSizeOptions]="[5, 10, 20]"></mat-paginator>
  </div>

类似的代码正在为其他组件工作,并且正确地使用分页呈现表,不知道此代码有什么问题。

任何帮助都会非常感激

35 个答案:

答案 0 :(得分:32)

我通过使用超时来围绕实例化解决了类似的问题。试试这个:

setTimeout(() => this.dataSource.paginator = this.paginator);

答案 1 :(得分:17)

在我的情况下,<mat-paginator>元素位于容器上,上面有一个*ngIf,直到异步加载数据后,该元素才呈现。即使在this.paginator中,这也会导致undefinedngAfterViewInit。由于MatTableDataSourcepaginator设置为undefined没问题,因此这会导致它默默地失败。

解决方案是将<mat-paginator>移出*ngIf容器之外

希望这对与我处境相同的人有所帮助。

答案 2 :(得分:12)

虽然选择的答案有效但解决了问题,但它仍然是一种解决方法。这是处理问题的正确和更优雅的方式。

尝试在您的课程中添加AfterViewInit界面,然后将this.dataSource.paginator = this.paginator放入ngAfterViewInit()方法

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

然后您就不必调用解决方法setTimeout

答案 3 :(得分:9)

这是因为this.paginator在分配给this.dataSource.paginator时未定义。

如果您使用静态数据,则可以使用

 @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; // For pagination
 @ViewChild(MatSort, {static: false}) sort: MatSort; // For Sort

 ngOnInit(): void {
   this.dataSource.data = this.dataList; // Data list is data array 
 }

 ngAfterViewInit(): void {
   this.dataSource.paginator = this.paginator; // For pagination
   this.dataSource.sort = this.sort; // For sort
 }

如果您使用动态数据(API中的数据),则可以使用

分页

  @ViewChild(MatPaginator, {static: false})
  set paginator(value: MatPaginator) {
    if (this.dataSource){
      this.dataSource.paginator = value;
    }
  }

用于排序

  @ViewChild(MatSort, {static: false})
  set sort(value: MatSort) {
    if (this.dataSource){
      this.dataSource.sort = value;
    }
  }

作为提示,我在机芯上使用Angular 9。

答案 4 :(得分:3)

尝试了所有上述提供的解决方案后,简单的解决方案终于对我有用。如果有人卡住,我将发布以供参考。

我正在使用Angular8。只需在子引用中添加{static:false}

  @ViewChild(MatSort, { static: false }) sort: MatSort;
  @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;

Got Solution From Here

我正在使用它:

<罢工> @ViewChild(MatSort,{阅读:是,静态:false})排序:MatSort;

@ViewChild(MatPaginator,{读:true,静态:false})分页器:MatPaginator;

答案 5 :(得分:3)

何时分页器在视图中可用并且可以检索并附加到数据源的问题是此问题的主要症结和常见陷阱。这里建议的解决方法包括使用setTimeout()ngAfterViewInit,它们很简单-类似于“让我们看看需要等待多少时间来确保@ViewChild设置了组件字段的解决方法具有正确的分页器值”。

正确的方法是将@ViewChild附加到属性设置器上,并在使用有效的分页器调用该设置器后尽快(且频次)设置数据源分页器。

只有一个数据源而不是每次加载都替换它(如我所见很多人所做的那样)也非常有用-只需将数据源绑定到mat-table并更新它的data字段

 <mat-table [dataSource]="dataSource" matSort>

      <ng-container matColumnDef="col1">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column1 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col1}} </mat-cell>
      </ng-container>

      <ng-container matColumnDef="col2">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column2 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col2}} </mat-cell>
      </ng-container>

      <!-- Different columns goes here -->

      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;">
      </mat-row>
    </mat-table>

    <mat-paginator #scheduledOrdersPaginator [pageSizeOptions]="[5, 10, 20]"></mat-paginator>
  </div>
dataSource: MatTableDataSource<any> = new MatTableDataSource();
displayedColumns = ['col1', 'col2', ... ];

@ViewChild('scheduledOrdersPaginator') set paginator(pager:MatPaginator) {
  if (pager) this.dataSource.paginator = pager;
}

@ViewChild(MatSort) set sort(sorter:MatSort) {
  if (sorter) this.dataSource.sort = sorter;
}

ngOnInit(): void {
    this.loadData().subscribe(somearray => { this.dataSource.data = somearray; });
}

此方法还应解决将分页器隐藏在*ngIf模板后面时将分页器渲染较晚的问题(此处注释者注意到)-即使分页器被渲染,也将被发送到数据源很晚。

答案 6 :(得分:2)

我花了好几个小时才弄明白。

关键是this.dataSource = new MatTableDataSource<MyInterface>(Object.values(data)); 然后设置this.dataSource.paginator = this.paginator;

我使用了 this.dataSource = data,虽然我可以获得数据,但分页不起作用。

你必须再次使用 new MatTableDataSource

适用于 Angular 11。

答案 7 :(得分:2)

以上解决方案均不适合我。

我弄清楚了问题所在,主要是this.paginator在表被加载并查看之前是不确定的,这就是为什么在某些setTimeout解决方案中起作用的原因。

但是在我的情况下,我的表隐藏在某些ngIf逻辑后面,因此仅在ngIf变为true之后才会加载该表(这在用户交互时发生),但是我设置了{{ 1}}在this.dataSource.paginator = this.paginator

因此,解决方案取决于您的情况,事实是确保只有在ngOnInit时才加载表

我通过以下方式解决了这一问题:当用户进行交互时,this.dataSource.paginator = this.paginator变成ngIf之后,我调用了设置分页器的函数

true

答案 8 :(得分:2)

设置数据源后立即调用ChangeDetectorRef.detectChanges():

// First import ChangeDetectorRef & Material related stuff
import { ..., ChangeDetectorRef } from '@angular/core';
import { MatSort, MatTableDataSource, MatPaginator } from '@angular/material';

// Set properties in your component
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;

// Inject in constructor
constructor (..., private cdr: ChangeDetectorRef, ...) { ... }

// Set data source and invoke detectChanges()
this.dataSource = new MatTableDataSource (MY_DATA);
this.cdr.detectChanges();

// after that you can set other properties like
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;

答案 9 :(得分:2)

我是有关angular和Typescript的初学者,但是在遇到相同的问题(对我来说,排序也不起作用)之后,创建了一个函数“ refreshDataScource()”并调用了它从ngAfterViewInit()开始,以及每次服务器响应新数据之后。在此函数中,我仅使用分页器和排序刷新dataSource。像这样:

refreshDataSource() {
    this.dataSource = new MatTableDataSource(myDataArray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

它修复了分页器和排序。现在一切正常。但是我不确定这只是解决方法还是真正的解决方法。

答案 10 :(得分:2)

要使其正常工作,我必须在从源中获取数据后设置分页器

getVariables() {
    this.activeRoute.params.subscribe(params => {
        if (params['id'] && (params['type'] === Type.CodeList)) {
            this.dataService
                .getItems(this.currentLanguage, params['id'])
                .subscribe((items: any) => {
                    this.dataSource.data = this.items;
                    this.dataSource.paginator = this.paginator;
                })
        }
    })
}

答案 11 :(得分:1)

对我有用的是实现关于ChangeDetectorRef的Lonely建议,并在@ViewChild中设置一个带有static:false的对象,如下所示:

  @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator;

答案 12 :(得分:1)

我遇到了同样的问题(显示了表数据,但MatPaginator无法正常工作)。 就我而言,我忘记创建“新的MatTableDataSource”

this.dataSource = somearray;

this.dataSource = new MatTableDataSource(somearray);启用时不启用MatPaginator。

material documentation提取

“”为简化使用具有可对数据数组进行排序,分页和过滤的表的用例,Angular Material库附带了一个 MatTableDataSource 已经实现了根据当前表状态确定应呈现哪些行的逻辑。”

希望这个答案对某人有帮助。

答案 13 :(得分:1)

使用 setTimeOut()可以暂时解决该问题,但是,如果将大量数据(例如1000行)推入MatDataSource中,这将再次失败。

我们发现,如果在设置数据源分页器之前设置了大数据集,则MatTable加载会非常缓慢。

ngOninit(){
// initialize dataSource here
}
    ngAfterViewInit() {
  this.dataSource.sort = this.sort;
  this.dataSource.paginator = this.paginator;

  /* now it's okay to set large data source... */
  this.dataSource.data = [GetLargeDataSet];}

因此,首先将数据源初始化,并设置诸如“ Paginator”或“ Sort”之类的属性,然后再将数据推入源中的“ Data”属性中。

答案 14 :(得分:0)

我遇到了类似的问题,因为我有两个带垫子分页器的垫子桌子,其中只有一个可以工作。我尝试了上述所有选项,然后我意识到我正在更新数据源对象而不是 datasource.data,没有意识到我正在更新类型,感谢@Bigeyes 分享他的答案。

表加载数据但分页器不工作:

this.datasource = data.filter(x => (x.planName == this.planName && x.Termed_y == 1))

表格加载数据和分页器工作:

this.dataSource2.data = data.filter(x => (x.planName == this.planName && x.Termed_y == 1))

答案 15 :(得分:0)

对我来说,只是添加属性MatPaginator.length。

<mat-paginator [length]="Elements.length"
               [pageSizeOptions]="[5, 10, 25, 100]">
</mat-paginator>

答案 16 :(得分:0)

n = 3
angle = 360 / n
for count in range(n):
  turtle.fd(50)
  turtle.lt(angle)
n = 4
angle = 360 / n
for count in range(n):
  turtle.fd(50)
  turtle.lt(angle)
n = 5
angle = 360 / n
for count in range(n):
  turtle.fd(50)
  turtle.lt(angle)

答案 17 :(得分:0)

第一个解决方案

从* ngIf div内部将mat-paginator移动到外部

第二个解决方案

在声明MatPaginator或MatSort时使用static false

@ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
@ViewChild(MatSort, {static: false}) sort: MatSort;

答案 18 :(得分:0)

我有一个类似的问题,mat-paginator放在一个ngIf的容器中。

对我唯一有用的是评论:

谢谢-这是我的解决方案。我选择使用[hidden]而不是ngIf,以便分页器即使没有数据也可以呈现,但不会向用户显示– TabsNotSpaces

为澄清起见,我所做的是在容器外部使用div创建一个[hidden]=<negation_of_the_same_condition_as_the_ngIf>

答案 19 :(得分:0)

ngOnInit()中使用 async-await 为我工作,分页器和排序必须等待!

   @ViewChild(MatPaginator) paginator: MatPaginator;
   @ViewChild(MatSort) sort: MatSort; 
    .
    .
    .
   ngOnInit() {
    this.isLoading = true;
    this._statsService.getAllCampgrounds().subscribe(
      async (response) => {
        this.allCampgrounds = response.allCampgrounds;
        this.dataSource = await new MatTableDataSource(this.allCampgrounds);
        
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;

        this.isLoading = false;
      },
      (error) => {
        this.isLoading = false;
        console.log(error);
      }
    );
  }

答案 20 :(得分:0)

在这种情况下,上面发布的所有答案都没有帮助我。

我的分页无法正常执行的原因是导入

e.x。

import {MatPaginator} from "@angular/material/paginator";

无法正常工作,因此我将此组件导入更改为

import { MatTableDataSource, MatPaginator, MatSort } from '@angular/material';

答案 21 :(得分:0)

我遇到了类似的问题。添加了以下内容来解决它。

第一步
将 ChangeDetectorRef 添加到构造函数 例如

constructor(private cdr: ChangeDetectorRef) 

步骤2
在init方法中调用检测变化方法和分页

this.cdr.detectChanges(); 
this.dataSource.paginator = this.paginator;

答案 22 :(得分:0)

@ViewChild(MatPaginator, {static: false}) paginator: any // For pagination
@ViewChild(MatSort, {static: false}) sort: any; // For Sort

像这样使用它会解决问题。

答案 23 :(得分:0)

对于低于7的Angular版本,对MatPaginator使用read参数。

@ViewChild(MatPaginator, {read: true}) paginator: MatPaginator;

这对我有用。

请注意,这适用于动态加载的表数据。

答案 24 :(得分:0)

仅当您知道加载表将花费多少时间时,才使用setTimeout()作为可行的解决方案。我的问题是我在桌子上使用* ngIf(带有!isLoading):

this.dataSource = new MatTableDataSource(this.rawData);

this.initPaginator();

this.isLoading = false;

此修复程序仅在检测到更改并初始化分页器之后才将我的isLoading变量设置为false:

this.dataSource = new MatTableDataSource(this.rawData);

this.isLoading = false;

this.cdr.detectChanges();

this.initPaginator();

因此它将加载数据->显示表格->检测到更改->在其分页器中。 我希望这对任何人都有帮助!

答案 25 :(得分:0)

确保已将MatPaginatorModule导入了app.module.ts

答案 26 :(得分:0)

要对表的数据进行分页,请在表后添加<mat-paginator>

如果您将MatTableDataSource用于表的数据源,只需将MatPaginator提供给数据源。它将自动侦听用户所做的页面更改,并将正确的分页数据发送到表。

否则,如果要实现对数据进行分页的逻辑,则将需要侦听分页器的(页面)输出并将正确的数据片段传递到表中。

有关使用和配置<mat-paginator>的更多信息,请查看mat-paginator文档。

MatPaginator是提供的一种用于对表数据进行分页的解决方案,但这不是唯一的选择。实际上,该表可以与任何自定义的分页UI或策略一起使用,因为MatTable及其接口未绑定到任何一种特定的实现。

@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
ngOnInit() {
  this.dataSource.paginator = this.paginator;
}

另请参阅 https://material.angular.io/components/table/overview

答案 27 :(得分:0)

请检查此Stackoverflow Answer

在加载HTML组件( * ngIf )之后,在打字稿中设置分页器为我解决了该问题。

答案 28 :(得分:0)

我也有这个问题。我将参考 scheduledOrdersPaginator 添加到了pagintaor标签中,并收到了 @ViewChild 。它解决了我的分页问题。下面的代码可能会帮助其他人。

dataSource = new MatTableDataSource();
displayedColumns = ['col1', 'col2', ... ];
@ViewChild('scheduledOrdersPaginator') paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit(): void {
    // Load data
    this.dataSource = new MatTableDataSource(somearray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

html:

<mat-paginator #scheduledOrdersPaginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons> </mat-paginator> 

答案 29 :(得分:0)

仅更改

dataSource: MatTableDataSource<any>;

dataSource = new MatTableDataSource();
dataSource = new MatTableDataSource();
displayedColumns = ['col1', 'col2', ... ];
@ViewChild('scheduledOrdersPaginator') paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit(): void {
    // Load data
    this.dataSource = new MatTableDataSource(somearray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

答案 30 :(得分:0)

我发现的解决方案是在成功加载数据后设置分页器。

import UIKit
import FirebaseDatabase
import Alamofire




class Vehicles: UITableViewController,
UISearchResultsUpdating, UISearchBarDelegate {

    //variables
    var model: NSMutableArray = []
    var numberOfVehicles: NSMutableArray = []
    var price: NSMutableArray = []
    var imagePathString: NSMutableArray = []
    var detailpage: NSMutableArray = []



    var populator: NSMutableArray = []
    var searching = false
    var matches = [Int]()
    let searchController = UISearchController(searchResultsController: nil)

    @IBOutlet weak var InfoTableView: UITableView!

    var InfoList: [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        loadData()
        //this should reload but, it didn't.
        self.InfoTableView.reloadData()
        //then the searchbar that is good and don't have any problem.
        searchingField()
    }



    func loadData() {
        //read data from database
        let rootRef = Database.database().reference()
        let conditionalRef = rootRef.child("Vehicles")
        conditionalRef.observe(.value) {(snap: DataSnapshot) in
            // Get all the children from snapshot you got back from Firebase
            let snapshotChildren = snap.children
            // Loop over all children in Firebase
            while let child = snapshotChildren.nextObject() as? DataSnapshot {
                // Get code node key and save it to they array
                self.populator.add(child.key)
                if self.populator.contains("\(child.key)") {
                    let userRef = rootRef.child("Vehicles").child("\(child.key)")

                    userRef.observeSingleEvent(of: .value, with: { snapshot in
                        let userDict = snapshot.value as! [String: Any]

                            let model1 = userDict["Model"] as! String
                            self.model.add(model1)

                            let detail1 = userDict["Detail"] as! String
                            self.detailpage.add(detail1)

                            let numberOfVehicles1 = userDict["numberOfVehicles"] as! String
                            self.numberOfVehicles.add(numberOfVehicles1)

                            let Price1 = userDict["Price"]  as! String
                            self.price.add(Price1)

                            let imageURL1 = userDict["imageURL"]  as! String
                            self.imagePathString.add(imageURL1)
                    }) //end second observeSingleEvent

                }
              else {
                    let alert = UIAlertController(title: "Error", message: "No one vehicle found", preferredStyle: UIAlertController.Style.alert)
                    alert.addAction(UIAlertAction(title: "ok", style: UIAlertAction.Style.default, handler: nil))
                self.present(alert, animated: true, completion: nil)
                }

            } //end searching object in Vehicles node



            } //end first observeSingleEvent

      }//end func


    func searchingField() {
        //setup searchbar
        tableView.estimatedRowHeight = 50
        navigationController?.navigationBar.prefersLargeTitles = true

        searchController.searchBar.delegate = self
        searchController.searchResultsUpdater = self
        searchController.searchBar.backgroundColor = UIColor.white
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "Search"
        navigationItem.searchController = searchController
        definesPresentationContext = true
        let attributes = [
            NSAttributedString.Key.foregroundColor : UIColor.black,
            NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 17)
        ]
        UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(attributes, for: .normal)
        UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).title = "Dismiss"
        UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self])
    }





    // MARK: Search Controller
    func updateSearchResults(for searchController: UISearchController) {
        var regArray = self.model as NSArray as! [String]
        if let searchText = searchController.searchBar.text,
            !searchText.isEmpty { 
            matches.removeAll()

            for index in 0..<model.count {
                if regArray[index].lowercased().contains(
                    searchText.lowercased()) {
                    matches.append(index)
                }
            }
            searching = true
        } else {
            searching = false
        }
        tableView.reloadData()
    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searching = false
        tableView.reloadData()
    }



    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return searching ? matches.count : model.count
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return searching ? matches.count : model.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cellIdentifier = "TableCell"

        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! Vehicles_cell



        let row = indexPath.row
        var regArray = self.model as NSArray as! [String]
        cell.Label.text = searching ? regArray[matches[row]] : model[row] as! String
        cell.Subtitle?.text = "N. Vehicles: \(self.numberOfVehicles[indexPath.row]) - Price: \(self.price[indexPath.row])$"


        Alamofire.request("\(self.imagePathString[indexPath.row])").response { response in
            guard let image = UIImage(data:response.data!) else {
                // Handle error
                return
            }
            let imageData = image.jpegData(compressionQuality: 1.0)
            cell.Image.contentMode = .scaleAspectFit
            cell.Image.image = UIImage(data : imageData!)
        }

        return cell
    }



    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "ShowrentDetails" {

            let myIndexPath = self.tableView.indexPathForSelectedRow!

            //save detail1 in UserDefault
            let SVDetail = self.detailpage[myIndexPath.row]
            let SVDetaildefaults = UserDefaults.standard
            SVDetaildefaults.set(SVDetail, forKey: "sv_detail")
            SVDetaildefaults.synchronize()
            _ = segue.destination
                as! Vehicles_Detail
        }
    }

    //IMPOSTA LE DIMENSIONI DELLE CELLE
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        switch indexPath.row {
        default:
            return 100
        }
    }


}

答案 31 :(得分:0)

这花了我几个小时终于找到了我的桌子为什么不工作。放置一些console.logs()可以帮助我弄清楚事件的顺序以及为什么它不能始终如一地工作。我的情况类似于上面的原始问题,带有动态数据源,但略有不同。对我来说,当我第一次刷新我的角度应用程序时,将设置分页器状态,然后设置表的数据。当这些事件按此顺序发生时,分页器将按预期工作。

由于我使用ReplaySubjects获取表的数据,因此我的分页器状态将在 ngAfterViewInit 中设置,然后表数据将来自我的订阅(取决于用户ID,所以我没有初始值,这就是为什么我不使用BehaviorSubjects的原因。我的问题是,当我导航到应用程序中的另一个组件并返回到动态表数据源时,表数据将在分页器状态之前设置。这将使分页器显示第x页,但显示的数据将始终是数据的第一页。

要解决此烦人的问题,我:

  1. 编写了一个简单的函数来将我的表数据设置为上述某人:
  setTableData() {
    // set table data
    this.tableData.data = this.images.filter(img => this.filterData(img));

    // some other code below
    ....
  }
  1. 在组件中添加了两个标志,一个标志用于是否加载了表数据,另一个标志用于设置了分页状态。这样,我可以确保在数据之前设置分页状态。
  // initialize our data source for our table and set flags for state
  tableData = new MatTableDataSource<IImage>(this.images);
  loading = true;
  setPageState = false;
  1. 向ngAfterViewInit添加了setTimeout,它仅在表数据通过之前调用ngAfterViewInit时才设置我的分页器状态并设置我的表数据。 setTimeout防止令人讨厌的“检查值后更改表达式”错误。
  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. 最后,在ngOnInit中,我预订数据的地方不要设置表数据,除非首先设置了分页器状态:
  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
    .....
  }

因此,当我第一次登录该应用程序时以及当我导航到其他页面并返回到动态表时,我的分页最终始终能够正常工作。

答案 32 :(得分:0)

在我的情况下,数据是来自服务的异步数据,因此它们都不能使用ngOnInit或ngAfterViewInit,而我使用的是ngOnChanges,如下所示:

ngOnChanges(change: SimpleChanges) {
    if (change.properties) {
      if (this.properties.length > 0) {
        this.dataSource = new MatTableDataSource(this.properties);
        this.dataSource.paginator = this.paginator;
      }
    }
  }

请确保将html上mat-table元素的[DataSource]属性设置为组件的数据源属性,以确保数据源与表和分页器绑定。

答案 33 :(得分:0)

不使用setTimeout的解决方案是使用set


 @ViewChild(MatPaginator) paginator: MatPaginator;


 set matPaginator(mp: MatPaginator) {
      this.paginator = mp;
      this.dataSource.paginator = this.paginator;
  }

答案 34 :(得分:0)

  <mat-paginator
        #scheduledOrdersPaginator
          (page)="pageEvent($event)">
        </mat-paginator>
         pageEvent(event){
         //it will run everytime you change paginator
           this.dataSource.paginator = this.paginator;
          }