Search code examples
angulartypescriptionic-frameworkngforion-checkbox

ionic angular *ngFor pipe


I am trying to understand why my *ngFor pipe filter does not get triggered, it works for "checkbox two" but not for "checkbox one", see example below.

I added two checkboxes that I want to trigger my pipe filter in *NgFor. How can I make "checkbox one" to trigger my NgFor PIPE filter? Does not seem like it get any change detected when using a json object as parameter. Also, did try detectChanges but that did not work.

View

<!-- checkbox one -->
<ion-checkbox labelPlacement="end" [checked]="checkbox_one.isChecked" (ionChange)="setColorOne(checkbox_one.isChecked)">filter one</ion-checkbox>

<!-- checkbox two -->
<ion-checkbox labelPlacement="end" [checked]="checkbox_two" (ionChange)="setColorTwo(checkbox_two)">filter two</ion-checkbox>
    
<div *ngFor="let index of [0,1] | color : checkbox_one"></div>
<div *ngFor="let index of [0,1]  | color : checkbox_two"></div>
    

Controller

  public checkbox_two = true;
  public checkbox_one =
    {
      isChecked: true
    }

  public setColorOne(color:any) {
    this.checkbox_one.isChecked = !color;
    //this.changeDetection.detectChanges();
  }

   
  public setColorTwo(color:boolean) {
    this.checkbox_two = !color;
  }

Pipe

  transform(items: any[], colors:any): any[] {
    console.log("PIPE");
    return items;
  }

Solution

  • There are 2 use cases: primitive type vs non primitive type.

    1. Primitive Type

    public checkbox_two = true;

      public setColorTwo(color: boolean) {
        this.checkbox_two = !color;
      }
    

    Your pipe can trigger any change from your variable because the value has been changed. Primitive type seems not have any problem.

    1. Non Primitive Type (Object)

    Remember the mechanism of pipe :

    When true, the pipe is pure, meaning that the transform() method is invoked only when its input arguments change

    In this case, the pipe isn't invoked because the argument has not changed :

     public setColorOne(color:any) {
        this.checkbox_one.isChecked = !color;
        //this.changeDetection.detectChanges();
      }
    

    You must update your object like that to tell your pipe that the reference has been changed:

      public checkbox_one = {
        isChecked: true,
      };
    
      public setColorOne(color: any) {
        this.checkbox_one = {
          isChecked: !color
        }
      }