Error value has changed after checked (Stateful Pipe in Angular2)

Chu Son

I have a simple Pipe that filter an array of students. Here's the code (Plnkr)

import {Pipe} from 'angular2/core';

@Pipe({
  name: 'sortByName',
  pure: false
})
export class SortByNamePipe {
  temp = [];
  // i = 0;
  transform (value, [queryString]) {
    // console.log(this.i++);
    // console.log(value, queryString);

    // This does not work
    this.temp = value.filter((student)=>(student)=>student.name.includes(queryString)))
    return value.map(function(val){ return val.name.toUpperCase()});

    // This works
    // this.temp.length = 0;
    // this.temp.push(...value.filter((student)=>student.name.includes(queryString)))        
    // return this.temp;
  }
}

As you can see in Plnkr, Angular throws an error using the first method.

EXCEPTION: Expression 'students | sortByName:queryElem.value  in HelloWorld@7:6' has changed after it was checked. Previous value: 'SON,DAVID'. Current value: 'SON,DAVID' in [students | sortByName:queryElem.value  in HelloWorld@7:6]

Why?

pixelbits

Angular cannot make certain optimizations for a stateful pipe, than it can for a stateless (or pure) pipe. For example, if a pipe is stateless, then it follows that the output of the filter only depends on its inputs (left | pipe:args). As long as 'left' or 'args' hasn't changed, then the output will not change. This allows AngularJS to safely skip the execution of the pipe when the inputs haven't changed.

For a stateful pipe, the output of the pipe can change, even for the same inputs.

The error is telling you that the array reference has changed, after it has been checked following the first round of change detection:

... has changed after it was checked. 
Previous value: 'SON,DAVID'. Current value: 'SON,DAVID'...

I've modified your first example to preserve the array reference:

// This now works
var $this = this; // save this
$this.temp.length = 0;
var tmp = value.filter((student)=>student.name.includes(queryString));
tmp.forEach(function (val) {$this.temp.push(val);});
return $this.temp;

[Edit]

As Mark pointed out, the error only occurs during development mode. If you change to production mode the error goes away, and the code works as expected.

[Explanation]

Apparently, in dev mode, angular will check your bindings twice to make sure they're not changing.

https://github.com/angular/angular/issues/6006

https://github.com/angular/angular/issues/6005

The problem is that when a binding changes after the first round of change detection, it will not trigger a new round of change detection. This is undesirable because the binding will not be updated until some future round of change detection. To ensure that this does not happen, Angular checks the bindings twice in development mode, and raises a run-time error when changes are detected.

Updated Plunkr

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Angular2 pipe causing '...has changed after it was checked' dev error

From Dev

Angular2 method binding error: "value has changed after it was checked"

From Dev

Angular2 - Error with two-way binding: Expression has changed after it was checked

From Dev

Angular2 change detection "Expression has changed after it was checked"

From Dev

Angular - Expression has changed after it was checked. Previous value

From Dev

Angular 2 "Expression has changed after it was checked"

From Dev

How to implement ngOnChanges for input validation on angular 2 without triggering ' Expression has changed after it was checked.' error

From Dev

Angular2 RC2 Expression has changed after it was checked.

From Dev

Angular2 (beta3) "expression has changed after it was checked" in updating form values

From Dev

Angular2: Nested *ngFor resulting in 'Expression has changed after it was checked'

From Dev

Angular2 ngClass docs & the Expression 'setClasses()’ has changed after it was checked exception

From Dev

Angular2 - Expression has changed after it was checked - Binding to div width with resize events

From Java

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'

From Java

Expression ___ has changed after it was checked

From Dev

Avoid the “Expression has changed after it was checked” error by calling "ChangeDetectorRef::detectChanges()"

From Dev

angular "Expression has changed after it was checked error" using moment.js

From Dev

Angular ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. cdkdrag

From Dev

Ionic 2 range slider causing "Expression value changed after it was checked" error

From Java

How to manage Angular2 "expression has changed after it was checked" exception when a component property depends on current datetime

From Dev

Angular 2 dynamic forms example with ngmodel results in "expression has changed after it was checked"

From Dev

FormBuilder Control causing "Expression has changed after it was checked" exception

From Dev

ngu-carousel :: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked

From Dev

How does angular2 detect the changes in a stateful pipe?

From Dev

angular2 - pipe error

From Dev

onReceive is not triggered after published value has changed

From Dev

Angular2 pipe dynamic value not taking

From Dev

Error handling with Angular2 async pipe

From Dev

How to ensure FormData is instantiated AFTER bootstrap has changed a radio input 'checked' status

From Dev

Run keydown event handler after the value of a <textarea> has been changed

Related Related

  1. 1

    Angular2 pipe causing '...has changed after it was checked' dev error

  2. 2

    Angular2 method binding error: "value has changed after it was checked"

  3. 3

    Angular2 - Error with two-way binding: Expression has changed after it was checked

  4. 4

    Angular2 change detection "Expression has changed after it was checked"

  5. 5

    Angular - Expression has changed after it was checked. Previous value

  6. 6

    Angular 2 "Expression has changed after it was checked"

  7. 7

    How to implement ngOnChanges for input validation on angular 2 without triggering ' Expression has changed after it was checked.' error

  8. 8

    Angular2 RC2 Expression has changed after it was checked.

  9. 9

    Angular2 (beta3) "expression has changed after it was checked" in updating form values

  10. 10

    Angular2: Nested *ngFor resulting in 'Expression has changed after it was checked'

  11. 11

    Angular2 ngClass docs & the Expression 'setClasses()’ has changed after it was checked exception

  12. 12

    Angular2 - Expression has changed after it was checked - Binding to div width with resize events

  13. 13

    ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'

  14. 14

    Expression ___ has changed after it was checked

  15. 15

    Avoid the “Expression has changed after it was checked” error by calling "ChangeDetectorRef::detectChanges()"

  16. 16

    angular "Expression has changed after it was checked error" using moment.js

  17. 17

    Angular ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. cdkdrag

  18. 18

    Ionic 2 range slider causing "Expression value changed after it was checked" error

  19. 19

    How to manage Angular2 "expression has changed after it was checked" exception when a component property depends on current datetime

  20. 20

    Angular 2 dynamic forms example with ngmodel results in "expression has changed after it was checked"

  21. 21

    FormBuilder Control causing "Expression has changed after it was checked" exception

  22. 22

    ngu-carousel :: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked

  23. 23

    How does angular2 detect the changes in a stateful pipe?

  24. 24

    angular2 - pipe error

  25. 25

    onReceive is not triggered after published value has changed

  26. 26

    Angular2 pipe dynamic value not taking

  27. 27

    Error handling with Angular2 async pipe

  28. 28

    How to ensure FormData is instantiated AFTER bootstrap has changed a radio input 'checked' status

  29. 29

    Run keydown event handler after the value of a <textarea> has been changed

HotTag

Archive