Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to put in angular template to check if a specific array contains an object with property that equals to some value?

I have the following in Angular:

<div *ngIf="myarrayContainsEating('Chocolate')">Chocolate Is Good</div>

In my component, I have:

myarray = [{'name':'Charles', 'age':25, 'eating':'Vanilla'}, {'name':'Joseph', 'age':18, 'eating':'Banana'}]

myArrayContainsEating(food) {

  let chocolateExists = false;
  for(var i = 0; myarray.length; i++) {
    if(myarray[i].eating == 'Chocolate') {
       chocolateExists = true;
    }
  }
  return chocolateExists;
}

The problem is, when I have a button where I hit it and make it so that Charles is eating 'Chocolate', it does not show the 'Chocolate Is Good' text I expect. Is there a way to make this work?

like image 231
Rolando Avatar asked Oct 24 '25 05:10

Rolando


2 Answers

Fixing your solution

Some problems with your code were already mentioned in other answers. Another thing to remind you of is the way you modify the eating property: You have to make sure to replace the array with a new array, each time an entry changes. Else the Change Detector will not pick up your changes.

You could do it like this:

Template

<div *ngIf="myarrayContainsEating('Chocolate')">Chocolate Is Good</div>

<button (click)="charlesEatChoc()">Make Charles eat Chocolate</button>

TS

myarray = [{'name':'Charles', 'age':25, 'eating':'Vanilla'}, {'name':'Joseph', 'age':18, 'eating':'Banana'}]

myarrayContainsEating(food) {
   return this.myarray.some(entry => entry.eating === food); // Check if any "eating" property is equal to food
}

charlesEatChoc() {
  this.myarray = this.myarray.map(entry => // This returns a new array (!!!IMPORTANT!!!)
     entry.name === 'Charles' // Map the entry if it matches your condition
        ? {...entry, eating: 'Chocolate'} // If it does, create a new one with the altered eating property
        : entry // If not, return the entry itself without modification
  );
}

Here is a working Stackblitz.

Cleaner solution

Calling a function inside an expression binding is not a good practice in Angular, since the Change Detector will have to rerun those methods each time there might have been a change. A cleaner way is to either hold a variable and change it accordingly (reactive apporach) or use a pipe.

Component template

<div *ngIf="myarray | containsFood:'Chocolate'">Chocolate Is Good</div>

<button (click)="charlesEatChoc()">Make Charles eat Chocolate</button>

Component TS

myarray = [{'name':'Charles', 'age':25, 'eating':'Vanilla'}, {'name':'Joseph', 'age':18, 'eating':'Banana'}]

charlesEatChoc() {
  this.myarray = this.myarray.map(entry => // This returns a new array (!!!IMPORTANT!!!)
     entry.name === 'Charles' // Map the entry if it matches your condition
        ? {...entry, eating: 'Chocolate'} // If it does, create a new one with the altered eating property
        : entry // If not, return the entry itself without modification
  );
}

Pipe TS

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'containsFood'
})
export class ContainsFoodPipe implements PipeTransform {

  transform(value: Array<any>, food:string): boolean {
     return value.some(entry => entry.eating === food); // Check if any "eating" property is equal to food
  }

}

Again, another working Stackblitz.

like image 180
pascalpuetz Avatar answered Oct 25 '25 17:10

pascalpuetz


Your final method should look like:

myArrayContainsEating(food) {
   let chocolateExists = false;
   for (let i = 0; i < this.myarray.length; i++) {
      if (this.myarray[i].eating == food) {
         chocolateExists = true;
      }
   }
   return chocolateExists;
}

The following are the issues with your code:

  1. Your if condition is incorrect. Change it to:

    if (myarray[i].eating === food) { 
       ... 
    }
    

    You need to access the eating property of each object. Nevertheless, the myArrayContainsEating(...) will still return false as there is no object in myArray array that has an object whose eating key contains the value chocolate. Thereby, the <div> will not be displayed.

  2. Also, you are missing a terminal condition in your loop:

    for(let i = 0; i < myarray.length; i++) {
       ...
    }
    
  3. Next, you need to use the parameter passed in the method i.e food to evaluate in the if expression.


Alternatively, you could easily just do:

myArrayContainsEating(food) {
   return this.myarray.find(e => e.eating === food);
}
like image 24
Nicholas Kurian Avatar answered Oct 25 '25 19:10

Nicholas Kurian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!