1

Using Angular 4. I have a paging.component that gets the page number and pageSize from it's parent component (after it gets data).

The paging.component will look for changes to the @Input's using the OnChanges life-cycle hook.

The paging.component also has a <select> input where you can change the pageSize.

During the OnInit phase, the <select> gets set to the pageSize passed in from the parent component.

If you change the pageSize with the <select>, it all works ok, but I sometimes also want to change the pageSize from the parent component to a different value (like the original value).

When I change the pageSize from the parent component, however, it does not change the <select> input. (Even though everything else seems to work correctly).

I tried adding the following code to the ngOnChanges method:

if (this.pageSizeFG) {
    this.pageSizeCtrl.setValue(this.pagesize);
}

However, this gives errors:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'.

The paging also seems to keep reseting itself to page 1 if I try to go to a different page.

I've looked into some of the other life-cycle hooks, ChangeDetectorRef, and ngZone, but those seem to make the problem worse.

I have created a plnkr here that demonstrates the error.

If you go to the paging.component.ts and comment out the line with this.pageSizeCtrl.setValue(this.pagesize);, then everything works fine EXCEPT the <select> does not update.

Joe Bell
  • 88
  • 7

1 Answers1

1

This is being caused by your ngModelChange event on your select element + your ngOnchanges lifecycle method.

<select (ngModelChange)="setPageSize($event)">...</select>

What is happening is

  1. you pass in a new input to paging.component
  2. ngOnChanges fires
  3. within ngOnChanges, this.pageSizeCtrl.setValue(this.pagesize) fires
  4. This causes the ngModelChange event to fire (setPageSize)
  5. setPageSize emits to the parent component
  6. parent changes input which causes ngOnChanges to fire again.

So this all leads to the Expression has changed error.

To fix this, I would use the change event instead of ngModelChange

<select (change)="setPageSize()">...</select>

This way setValue() does not cause the setPageSize() event to fire. You will also need to update how setPageSize() emits the pageSize property.

setPageSize() {
    // get pageSizeCtrl value programatically
    let pageSize = +this.pageSizeCtrl.value;
    this.pagechange.emit({ page: 1, pageSize: pageSize });
}

Here is a working plnkr with the fixes (http://plnkr.co/edit/zJEIYJzG5OGRXIfA77Qz?p=preview)

LLai
  • 13,128
  • 3
  • 41
  • 45