【问题标题】:Angular 5 Material Paginator resets to negative values when updating pageIndex更新 pageIndex 时,Angular 5 Material Paginator 重置为负值
【发布时间】:2018-11-15 04:25:04
【问题描述】:

我正在使用 Angular Material 数据表来显示可以添加到的对象列表。将对象添加到数据源时,页面索引会中断并显示负数。我发现解决此问题的唯一方法是将材料分页器的页面索引重置为 0。但是,对分页器的任何进一步更改都会导致 pageIndex 为 -1 或分页器损坏。这是一个例子:

我首先在 Angular Material 数据源中设置新数据,如下所示:

private refreshTable() {
    // first we update the length of the paginator with the new length of the datasource data to ensure parity
    this.paginator.length = this.dataSource.data.length;


    // next we get the current page number so we can return to it later.
    let currentPage = this.paginator.pageIndex;

    this.tempSubscription2 = this.rrService.getSearchResults(this.searchEnv.outputPayload(true, true)).subscribe(
        (data: any) => {
            this.extractSBRs(data);
            this.dataSource.data = [];
            // Here is where the dataSource is reset...
            this.dataSource.data = this.sbrs;

            this.paginator.length = this.dataSource.data.length;
            this.paginator.pageIndex = 0;
            this.dataSource.paginator = this.paginator;
            console.log('made it this far');

            if (this.dataSource.paginator.pageIndex < currentPage) {
                console.log('need to return to the current page');
                this.paginator.pageIndex = currentPage;
                this.paginator._pageIndex = currentPage;
                this.dataSource.paginator.pageIndex = currentPage;
                this.dataSource.paginator._pageIndex = currentPage;

            }
        },
        (err: any) => {
        },
        () => {
        }
    );
}

运行此代码时,从第一页开始更新就可以了,因为 this.paginator.pageIndex 被设置为 0。一旦在大于零的页面上添加元素,表格将显示第一页,分页器有pageIndex 为 -1,UI 中的分页器如下所示:

注意负索引-9 - 0。似乎很少有更新 Angular Material Data Table 的示例,甚至更少有关于更新它们如何影响 Angular Material 分页器的进一步说明。如何让分页器转到 0 以外的 pageIndex 而不会出现负索引问题?

我尝试只更新this.paginator,它是根据here 的建议通过ViewChild() 获取的。我还尝试更新您可以在上面的代码中看到的dataSource.paginator

这是我的导入:

import {
AfterContentInit, AfterViewInit, ApplicationRef, ChangeDetectorRef, 
Component, OnDestroy, OnInit,
    ViewChild
} from '@angular/core';
import { SearchEnvironment } from "../classes/search-environment";
import { SearchFilterDropdown } from "../classes/search-filter-dropdown";
import { ActivatedRoute, Router } from "@angular/router";
import {MatTableDataSource, MatPaginator, MatDialog, MatTable, MatSnackBar} from "@angular/material";
import { RemoteRetrievalService } from "../core/services/remote-retrieval.service";
import { Observable } from "rxjs/Observable";

如何在不导致 paginator.pageIndex 值中的负索引或项目范围内的负值的不良用户体验的情况下获得返回到 currentPage 索引的所需分页器行为?

【问题讨论】:

    标签: angular pagination angular-material2


    【解决方案1】:

    他们是如何构建这些组件的,这很奇怪。我不确定我的解决方案是否有效,但根据我在该问题中所读到的内容,他们似乎无法在同一摘要周期中同时处理 length 更改和 pageIndex 更改。

    所以我建议先更改length,然后再更改pageIndex

     this.paginator.length = this.dataSource.data.length;
     this.paginator.pageIndex = 0;
     this.dataSource.paginator = this.paginator;
     console.log('made it this far');
    

    上面设置了我们知道将在组件上起作用的值,下一部分使用window.setTimeout 在组件有机会自我更新后运行下一组更改。

     if (this.dataSource.paginator.pageIndex < currentPage) {
         window.setTimeout(()=>{
             this.zone.run(()=>{
                console.log('need to return to the current page');
                this.paginator.pageIndex = currentPage;
                this.paginator._pageIndex = currentPage;
                this.dataSource.paginator.pageIndex = currentPage;
                this.dataSource.paginator._pageIndex = currentPage;
                // EDIT: You must then set the datasource paginator back to the newly edited paginator. 
                this.dataSource.paginator = this.paginator;
             });
         });
     }
    

    您需要注入 NgZone 以在 Angular 的区域内运行代码(用于错误处理)。这只是使用window.setTimeout 时的一个好习惯。

    请记住,Angular Universal 中不存在 window,以防您以后想进行服务器端渲染,但这是一个不同的问题。

    【讨论】:

    • 我现在就试试这个。谢谢您的回答!我会告诉你进展如何。
    • 使用此解决方案,负索引从分页器中消失。所以这是一场胜利。不幸的是,表格仍然返回到导致分页器和表格不同步的第一页。有任何想法吗?我会看一下索引,以确保它不简单。
    • 索引似乎正确,但表格仍然返回第一页。
    • 您的解决方案是正确的,我会接受您的回答。我提交了一个编辑,因为在我添加了一行代码之前它不能完全工作。没有你的帮助,我无法解决它。谢谢!
    • 谢谢它对我有用。 Allthought,如果你已经准备好使用 Angular,你不必执行 zone.run 。看看静态 bool IsInAngular :angular.io/api/core/NgZone#isinangularzone
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 1970-01-01
    • 2020-04-04
    • 2019-01-06
    • 2019-11-28
    相关资源
    最近更新 更多