Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it poor practice to use very similar for loops in two places with Angular 6?

I'm generating two lists for a roster.

One list to show the current members of that year, and a second list if people have been excused in that year.

I noticed that I have two of the same for loops except one prints out all of the true Boolean values, and one the false. Is there a better way (or a method of some sort) to print out the people who are excused and not excused?

<h2>Roster {{year-1}}-{{year}}</h2>

<div *ngFor="let k of peoples">
  <div *ngFor="let a of k.people; let j = index">
    <div *ngIf="k.year == year && k.people[j].excused == false">
      {{k.people[j].firstName}} {{k.people[j].lastName}}
    </div>
  </div>
</div>

<h2>Excused</h2>

<div *ngFor="let k of peoples">
  <div *ngFor="let a of k.people; let j = index">
    <div *ngIf="k.year == year && k.people[j].excused == true">
      {{k.people[j].firstName}} {{k.people[j].lastName}}
    </div>
  </div>
</div>
like image 891
Happy Sheep Avatar asked Sep 11 '18 17:09

Happy Sheep


People also ask

Is the for loop outdated?

'For' loops are considered obsolete, hence we should avoid using them. In single threaded languages like JavaScript, the 'for' loop acts as a thread blocker, which hinders the scalability of a system.

When might the for of loop not be the appropriate choice?

When not to use them? If you want to swap elements of an array, if you want to reverse order. You can't even increment the values by 1 and store them back into the array, because for that, you would need to know their corresponding key.

Which loop is better for or forEach?

The for-each loop should generally be preferred. The "get" approach may be slower if the List implementation you are using does not support random access. For example, if a LinkedList is used, you would incur a traversal cost, whereas the for-each approach uses an iterator that keeps track of its position in the list.

Is map () more efficient than for loop?

Comparing performance , map() wins! map() works way faster than for loop. Considering the same code above when run in this ide.


2 Answers

It would be better to use it this way without additional *ngIf.

As mentioned in comments it would be better to prepare to separete arrays for data in the component and do it once after data updated. But since the context of usage is unknown this looks like a better solution. You need to avoid *ngIf if you can filter data in array to prevent from unnecessary work another structure directive in template. It always gives you perfomance advanateges.

In your component you can define filter function:

getExcused(isExcused: boolean) {
    return this.peoples
        .filter(k=>k.year === this.year)
        .map(k=>k.people)
        .filter(p=>p.excused === isExcused);
}

Then in template:

<h2>Roster {{year-1}}-{{year}}</h2>
<div *ngFor="let a of getExcused(false)">
    {{ a.firstName }} {{ a.lastName }}
</div>
<h2>Excused</h2>
<div *ngFor="let k of getExcused(true)">
    {{ k.firstName }} {{ k.lastName }}
</div>

If your component uses change detection strategy on push it won't make any perfomance issues.

like image 123
Dmitriy Snitko Avatar answered Nov 13 '22 00:11

Dmitriy Snitko


Maybe I'am wrong, but isn't a pipe the prefered way of doing this ? Or better, you could chain 2 pipes !

<div *ngFor="let k of peoples| yearPipe: year | excusedPipe: no">

      {{k.people[j].firstName}} {{k.people[j].lastName}}

</div>

<h2>Excused</h2>

<div *ngFor="let k of peoples| yearPipe: year | excusedPipe: yes">

      {{k.people[j].firstName}} {{k.people[j].lastName}}

</div>

@Pipe({ name: 'yearPipe' })
export class YearPipe implements PipeTransform {
  transform(allPeople: People[], year: string) {
    return allPeople.filter(person => person.year == parseInt(year));
  }
}

@Pipe({ name: 'excusedPipe' })
export class ExcusedPipe implements PipeTransform {
  transform(allPeople: People[], excused: string) {
    if (excused === 'yes'){
       return allPeople.filter(person => person.excused);
    }else{
       return allPeople.filter(person => !person.excused);
    }
  }
}

The only tricky part is that the parameter to the pipe is allways string, or that is what I find in docs in Angular.io

Edit : refer to this stackblitz example ( Chained Pipes example ): https://stackblitz.com/edit/angular-rb5vmu

like image 24
wFitz Avatar answered Nov 13 '22 01:11

wFitz