0
votes

I'm using a function that returns a boolean to set the items visibility using the hidden attribute inside a ngFor loop.

const countries = [
   {country: 'USA', hide: 'false'},
   {country: 'UK', hide: 'false'},
   {country: 'Germany', hide: 'true'},
   {country: 'France', hide: 'true'},
   {country: 'Japan', hide: 'false'},
   {country: 'Russia', hide: 'false'}
 ]

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
    </div>
    <my-list></my-list>
  `,
})
export class App {
  name:string;
  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }
}

@Component({
  selector: 'my-list',
  template: `
    <ul>
      <li *ngFor="let l of list" [hidden]="setVisibility(l)">{{l.country}}</li>
    </ul>
  `,
})
export class List implements OnInit {
  list;
  ngOnInit(){
    this.list = countries  
  }

  setVisibility(country){
    console.log('setting');
    let hide = false;
    if(country.hide === 'true'){
      hide = true;
    }
    return hide;
  }
}

I put a console.log inside the setVisibility method to check how many times this method is called. I expected it to be called 6 times (1 time per item) but it's actually called 24 times ( 4 times per item). Why is this method called so many times? plunker

1
It can be even more, it's about how angular reads your function for binding, btw it's better not using functions in bindings, instead in your cause I would say it's better to do it like [hidden]="l.hide === 'true'" - Reza
I've simplified the function a bit for showing it, but actually the function should loop through object properties to set visibility and doesn't fit on the template - Diego Vega
I prove the plunker and it only 4 times - alehn96
Did you open the console? I got the log 12+12 times on the first load and 6+6+6+6 every time I change the plunker - Diego Vega

1 Answers

2
votes

As RezaRahmati mentioned, it can be called even more. Right now there are you four basic component lifecycle hooks being called, and that's likely why you're receiving four calls per item. If you were to change the data, the function would be called again (likely twice per change). Since ngFor is dependent on changes in the data it will re-render and call the function as needed.

Also, as mentioned, setting your [hidden] by directly accessing the variable is going to be a much faster process (even though it will be called just as many times as your function was). This is simply how Angular works at managing these dynamic variables. Here's a small plunker to show you how something like this is typically done:

TypeScript variable:

 const countries = [
   {country: 'USA', hide: false},
   {country: 'UK', hide: false},
   {country: 'Germany', hide: true},
   {country: 'France', hide: true},
   {country: 'Japan', hide: false},
   {country: 'Russia', hide: false}
 ]

Component Template:

<ul>
  <li *ngFor="let l of list" [hidden]="l.hide">{{l.country}}</li>
</ul>