My Angular 4 application has a Component that has a refresh
method that pulls-in a large object from my web-service, like so:
DTOs/Model types:
class NuclearReactorStatus {
public reactorName: string;
public coolingRods: CoolingRodStatus[]; // array of 1024 elements
}
class CoolingRodStatus {
public rodId : number;
public temperature: number;
public status : string;
}
Inside the NuclearReactorDisplayComponent
:
public reactorStatus: NuclearReactorStatus;
refresh(): void {
this.http.get<NuclearReactorStatus>()
.subscribe(
status => {
this.reactorStatus = status;
},
err => {
console.error( err );
}
);
}
Inside my nuclearreactordisplay.component.html
<h1>Reactor {{reactorStatus.reactorName}}</h1>
<h2>Cooling rods</h2>
<ol *ngIf="reactorStatus.coolingRods">
<li *ngFor="let rod of reactorStatus.coolingRods"
[data.rod-id]="rod.rodId"
[data.rod-temperature]="rod.temperature"
class="{{ rod.temperature < 100 ? "cool" : rod.temperature < 1000 ? "warm" : rod.temperature < 10000 ? "hot" : "jalapeno" }}"
>
<span>{{rod.rodId}}</span>
</li>
</ol>
I'm styling the rod <li>
elements by arranging them into a grid:
ol {
display: flex;
flex-wrap: wrap;
list-style: none;
width: calc( 32 * 16px ); // grid is 32 elements wide, 32x32 == 1024
}
li {
display: block;
width: 16px;
height: 16px;
transition: background-color 0.2s;
}
li span {
display: none;
}
li.cool { background-color: black; }
li.warm { background-color: orange; }
li.hot { background-color: yellow; }
li.jalapeno { background-color: red; }
Note my use of transition: background-color
so the rod's box's background color changes gradually instead of suddenly.
When I run my program, I notice that Angular actually replaces the <ol>
and all child <li>
elements each time the data refreshes instead of using the existing DOM and updating the class
attributes - so my background-color
transition never happens - but more alarmingly the CPU usage on my computer skyrockets because of the expense of manipulating the DOM this way.
How do I get Angular to re-use the <ol>
and <li>
elements it created in the template instead of deleting and recreating them on every refresh cycle?
Since
ngFor
may preform bad when the data list is huge, Angular has provided atrackBy
which you can tell angular how to replace existing DOM elements. See details here.TrackByFun: