Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(paginator): not emitting page event when pageIndex, pageSize or length changes #12586

Closed
wants to merge 1 commit into from

Conversation

crisbeto
Copy link
Member

@crisbeto crisbeto commented Aug 8, 2018

Currently the paginator won't fire the page event if it's pageIndex, length or pageSize change, which means that the associated table won't be able to react. These changes emit the event if the values change.

Fixes #12583.

@crisbeto crisbeto added the target: patch This PR is targeted for the next patch release label Aug 8, 2018
@crisbeto crisbeto requested a review from andrewseguin as a code owner August 8, 2018 14:40
@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Aug 8, 2018
if (newPageSize !== this._pageSize) {
this._pageSize = newPageSize;
this._updateDisplayedPageSizeOptions();
this._emitPageEvent(this.pageIndex);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also markForCheck?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it needs to since it's going through an Output. At least in my testing it wasn't necessary.


if (newLength !== this._length) {
this._length = newLength;
this._emitPageEvent(this.pageIndex);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since alot of usages of the MatPaginator with a DataSource update the length whenever the data updates, this could cause a loop of sorts.

The if block would prevent it from happening more than once, but we still would be triggering the DataSource's value multiple times.

An example can be seen here with the table-data-source.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't the table user the IterableDiffer under the hood? That should prevent it from doing extra work even if it does fire multiple times. I'm fine with cutting down the PR so it only addresses the pageSize as mentioned in #12583, but I can imagine people running into the same issue for the other two properties.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We just got another issue about the pageIndex: #12620.

@jelbourn
Copy link
Member

Something does feel weird about this change. Andrew would have a better idea, but I vaguely recall the decision for page events to emit on user interaction being intentional. The thinking was probably that if the user is setting new values into the paginator, they obviously already know about those values and should also propagate them to wherever else they're needed. This makes the page event consistent with change events from other components, which also do this, mirroring native html controls.

@crisbeto
Copy link
Member Author

I suppose the difference between the page event and the various change events is that page is also being used internally inside the table data source in order to know when to re-render the data.

@jelbourn
Copy link
Member

Mind if we sit on this one for a few weeks until Andrew gets back? I'd like to chat with him about it.

@ngbot
Copy link

ngbot bot commented Oct 23, 2018

Hi @crisbeto! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

@crisbeto crisbeto force-pushed the 12583/paginator-events branch from 7b0531c to 19e617f Compare October 23, 2018 19:28
@dchennells
Copy link

dchennells commented Dec 19, 2018

The page index is typically set to zero in user code in response to sort changes and filter changes, which typically themselves already result in table-reloading chains of events including calls to a service or repository. (While an application-user might be half-way through a long paginated list, they are generally assumed to want to be placed at the top of the reformulated list when the sort or filter changes appear. Sort and filter changes render page position meaningless or at least ambiguous; and, by convention, sorting is seldom implemented on a paginated-page-local basis.) If MatPaginator.page fires as a result of this reset in code to the first page, a second, redundant call on the datasource would be caused under common circumstances, unless user code implements some sort of gating or temporal windowing/debouncing mechanism.

Overall, this change might cause some inconvenience for alert developers, and, a subtle bandwidth and performance loss for less-alert developers. (Subtle, because it will be triggered only if the page number is not already zero at the time the filter or sort change is made; we are talking about an extra, back-end call in SPAs; and, finally, it might not jump off the page for some devs less familiar with asynchronous reactive subscription lambda syntax.) If this breaking change is to be made, then perhaps it should be mitigated by adding a new MatPaginator method that goes to the first page without triggering the MatPaginator.page event and to disseminate knowledge (e.g. in the examples) that this call should be used in lieu of this.paginator.pageIndex = 0 in this scenario.

For typical current user code, consider the following excerpt from the "Table retrieving data through HTTP" mat-table example in the API docs online.

ngOnInit() {
    this.exampleDatabase = new ExampleHttpDao(this.http);

// If the user changes the sort order, reset back to the first page.
    this.sort.sortChange.subscribe(() => **this.paginator.pageIndex = 0**);

    merge(**this.sort.sortChange, this.paginator.page**)
      .pipe(
        startWith({}),
        switchMap(() => {
          this.isLoadingResults = true;
          return this.exampleDatabase!.getRepoIssues(
            this.sort.active, this.sort.direction, this.paginator.pageIndex);
        }),
        map(data => {...

(Incidentally, I found this issue when I sought to confirm that, as things stand, I would not have to intercept/block incident calls to my datasource indirectly caused by my component filtering and sort event-handling functions.)

crisbeto added a commit to crisbeto/material2 that referenced this pull request Dec 28, 2018
…than the current page

Fixes the table not rendering correctly when going from a large set of data (e.g. 50 items and on page 10) to a small set of items (e.g. 1 item). The issue comes from the fact that the paginator doesn't emit events if they weren't generated by the user (see discussion on angular#12586).

Fixes angular#14010.
crisbeto added a commit to crisbeto/material2 that referenced this pull request Dec 28, 2018
…than the current page

Fixes the table not rendering correctly when going from a large set of data (e.g. 50 items and on page 10) to a small set of items (e.g. 1 item). The issue comes from the fact that the paginator doesn't emit events if they weren't generated by the user (see discussion on angular#12586).

Fixes angular#14010.
vivian-hu-zz pushed a commit that referenced this pull request Jan 16, 2019
…than the current page (#14665)

Fixes the table not rendering correctly when going from a large set of data (e.g. 50 items and on page 10) to a small set of items (e.g. 1 item). The issue comes from the fact that the paginator doesn't emit events if they weren't generated by the user (see discussion on #12586).

Fixes #14010.
s2-abdo pushed a commit to s2-abdo/material2 that referenced this pull request Jan 18, 2019
…than the current page (angular#14665)

Fixes the table not rendering correctly when going from a large set of data (e.g. 50 items and on page 10) to a small set of items (e.g. 1 item). The issue comes from the fact that the paginator doesn't emit events if they weren't generated by the user (see discussion on angular#12586).

Fixes angular#14010.
s2-abdo pushed a commit to s2-abdo/material2 that referenced this pull request Jan 18, 2019
…than the current page (angular#14665)

Fixes the table not rendering correctly when going from a large set of data (e.g. 50 items and on page 10) to a small set of items (e.g. 1 item). The issue comes from the fact that the paginator doesn't emit events if they weren't generated by the user (see discussion on angular#12586).

Fixes angular#14010.
vivian-hu-zz pushed a commit that referenced this pull request Jan 18, 2019
…than the current page (#14665)

Fixes the table not rendering correctly when going from a large set of data (e.g. 50 items and on page 10) to a small set of items (e.g. 1 item). The issue comes from the fact that the paginator doesn't emit events if they weren't generated by the user (see discussion on #12586).

Fixes #14010.
@mmalerba mmalerba added aaa and removed aaa labels Apr 25, 2019
@crisbeto crisbeto force-pushed the 12583/paginator-events branch from 19e617f to 4c93b61 Compare May 26, 2019 13:13
@andrewseguin andrewseguin added the P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent label May 30, 2019
@singulli1
Copy link

Any updates on this?

…ength changes

Currently the paginator won't fire the `page` event if it's `pageIndex`, `length` or `pageSize` change, which means that the associated table won't be able to react. These changes emit the event if the values change.

Fixes angular#12583.
@crisbeto crisbeto force-pushed the 12583/paginator-events branch from 4c93b61 to c8b7edb Compare February 11, 2020 21:12
@andrewseguin andrewseguin added the needs: discussion Further discussion with the team is needed before proceeding label Jun 12, 2020
Copy link
Contributor

@andrewseguin andrewseguin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of our components have a stateChanges stream that emits when inputs are changed. I think that would be better suited for this case. The MatTableDataSource could watch for changes off that stream and re-render. For users that have their own data source, they can either listen for that stream or otherwise handle what they provide to the table when these inputs are changed.

@andrewseguin andrewseguin removed the cla: yes PR author has agreed to Google's Contributor License Agreement label Dec 29, 2021
@andrewseguin andrewseguin removed the P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent label Mar 28, 2022
@josephperrott josephperrott added action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews and removed needs rebase labels Nov 16, 2022
@josephperrott josephperrott requested a review from a team as a code owner December 18, 2024 17:40
@josephperrott josephperrott requested review from amysorto and mmalerba and removed request for a team December 18, 2024 17:40
@mmalerba
Copy link
Contributor

Closing per Andrew's comment above that we would prefer something like a stateChanges stream (or at this point, maybe signals)

@mmalerba mmalerba closed this Feb 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews needs: discussion Further discussion with the team is needed before proceeding target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Paginator] Does not update correctly when pageSize updated programatically
8 participants