Search code examples
angularionic-frameworkionic4ngfor

Trigger manually ngFor or making it update DOM correctly


i have this code

TS

modal.onDidDismiss().then(res => {
  if (res.data !== undefined) {
    this.foodAllergies.push(res.data)
    if (this.categories.length === 0) {
      this.categories.push(res.data.category)
    } else {
      if (!this.categories.includes(res.data.category)) {
        this.categories.push(res.data.category)
      }
    }
  }
});

HTML

<ion-grid>
    <ion-row *ngFor="let category of categories">
      <ion-col>
        <h3>{{category}}</h3>
        <ion-list>
          <ion-item *ngFor="let food of foodAllergies | categoryFilter: category">
            <ion-label>{{food.name}}</ion-label>
          </ion-item>
        </ion-list>
      </ion-col>
    </ion-row>
  </ion-grid>

So whenever i add a new category to the categories array, the view updates correctly showing the foods that are in that category The problem is that when i add a category which is already present in the categories array, the view doesn't update correctly because the second ngFor doesn't trigger it doesn't add the food with that category

How can i solve this problem?


Solution

  • Your if() { ... } else { if() { ... } } are doing the same thing, I find that strange.

    Try updating foodAllergies in an immutable way (changing its reference) and see if that helps and kicks on change detection.

    modal.onDidDismiss().then(res => {
      if (res.data !== undefined) {
        this.foodAllergies = [...this.foodAllergies.map(foodAllergy => ({...foodAllergy})), res.data];
        this.foodAllergies.push(res.data);
        // you can keep your if and else if but I have removed them here for this example
        this.categories.push(res.data.category);
       }
      }
    });
    

    For ...this.foodAllergies.map(foodAllergy => ({...foodAllergy})), depending on how many deeply nested objects/arrays you have in foodAllergy, you have to copy them immutably.

    So say if foodAllergy looks like { name: 'Peanuts', x: [1, 2, 3], y: { a: 1, b: 2 } }, it will become:

    ...this.foodAllergies.map(foodAllergy => ({
                                                ...foodAllergy, 
                                                x: [...foodAllergy.x], 
                                                y: {... foodAllergy.y } 
                               }))