-1

This is an simple example, real problem is more complex.

cars: string[] = ['audi', 'opel', 'mazda'];
isAudi: boolean = false;
isOpel: boolean = false;

checkCar(car):void {
    if(car == 'audi'){
        this.isAudi = true;
    }
}

<div *ngFor="let car of cars" (validationCheck)="checkCar(car)">
    <p *ngIf="isAudi">Audi: {{car}}</p>
    <p *ngIf="isOpel">Opel: {{car}}</p>
</div>

validationCheck is directive that triggers function for every item in array.

This will output:

Audi: audi
Audi: opel
Audi: mazda

I want only to show:

Audi: audi

*ngIf="car == 'audi'" is out of the question because of real complexity of object.

Ps. if you want to downvote a question, give me a good explanation why question does not show research effort or its unclear or not useful, thx

dev_in_progress
  • 2,484
  • 2
  • 21
  • 32
  • Why do you think is the object complex? – Nabin Paudyal Jan 29 '18 at 09:50
  • Because i need to do several different conditions to show that part, for example `*ngIf="car && car.manufacturer && manufacturers.get(car.manufacturer.id).manufacturer.name == 'fiat'....... and so on"...` a big pile of conditions is here that is hard to maintain so i want to put it in component file – dev_in_progress Jan 29 '18 at 09:56
  • How about adding a boolean field, something like `show` to each of the cars? – Nabin Paudyal Jan 29 '18 at 10:03
  • Is it not possible to make a method to write all of your complex logic in one place and add it in the template `*ngIf="yourComplexMethod()"` ? By this approach you dont need to use (validationCheck) with `*ngFor` – Ashraful Islam Jan 29 '18 at 11:42
  • With that approach function is called on every change detection cycle. I want to avoid that. – dev_in_progress Jan 29 '18 at 11:52
  • @NabinPaudyal that wont work – dev_in_progress Jan 29 '18 at 11:58

1 Answers1

1

You're not on the right track.

The flag "isAudi" is bound to each car: each car is an audi or is not. So the flag should be in the car, not in the component. Or it should be computed from a car.

So, solution one:

<div *ngFor="let car of cars">
  <p *ngIf="isAudi(car)">Audi: {{car}}</p>
  <p *ngIf="isOpel(car)">Opel: {{car}}</p>
</div>

isAudi(car: string) {
  return car === 'Audi';
}

isOpel(car: string) {
  return car === 'Opel';
}

Second solution, if the above causes performance problem because isAudi() is really complex to compute (which I doubt), use objects, precompute isAudi and isOpel when you get the data, and store it with the car:

interface FlaggedCar {
  car: string;
  isAudi: boolean;
  isOpel: boolean;
}

this.flaggedCars = cars.map(car => {
  return {
    car,
    isAudi: this.isAudi(car),
    isOpel: this.isOpel(car)
  }
});

<div *ngFor="let flaggedCar of flaggedCars">
  <p *ngIf="flaggedCar.isAudi">Audi: {{flaggedCar.car}}</p>
  <p *ngIf="flaggedCar.isOpel">Opel: {{flaggedCar.car}}</p>
</div>

Of course, this supposes that a car is not modified and doesn't become an Opel. Or the flag must be recomputed each time the car changes (which makes this solution more complex).

But again, you probably don't need this complexity, because isAudi() and isOpel() are probably fast enough to be called from the view.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Nice explanation, thx. "isAudi() and isOpel() are probably fast enough", yes they are but then they are called on every change detection cycle, if called from view, is this a good approach? – dev_in_progress Jan 29 '18 at 12:58
  • If it's fast enough, it's fast enough, right? Now of course, if you target old mobile devices and want to save battery as much as possible, you can overoptimize, but generally, premature optimization is the root of all evil. – JB Nizet Jan 29 '18 at 13:02
  • Good point, do you have any suggestions on how to approach this problem or prefered way? Inline view condition, function call from component or something third? – dev_in_progress Jan 29 '18 at 13:19
  • Isn't that clear from my answer? I suggest using the first solution, or the second if optimization is really needed. – JB Nizet Jan 29 '18 at 13:20