I have a component which is basically a list of items, where each item contains a name and a row of boxes. Something like this (but styled): John Doe [1][2][3][4][5] Each box represents a task, each task is either "approved" or "not approved". If it's approved it's green, if not then grey. The data for each item is passed through from a Element object which also has an array of Task objects as one of its values and each box is attached to a (click) listener which toggles the value of task.approved and the color of the box, accordingly.
The problem arises when there are a lot of items in the list. I tested it with 90 items and each time I click on a box it takes up to 300ms to change its color.
I tried a lot of different ways of rectifying this, here is the first iteration of the HTML:
<md-list>
<md-list-item *ngFor="let item of testData" class="flex-container">
<div style="margin-left:10px;"> {{item.firstName + " " + item.lastName}}</div>
<div class="boxes">
<div *ngFor="let task of item.tasks;" style="cursor: pointer;" >
<div *NgIf="task.approved" class="flex-item box" style="background-color: green;" (click)="task.approved = !task.approved">{{task.taskNumber}}</div>
<div *NgIf="!task.approved" class="flex-item box" style="background-color: lightgrey;" (click)="task.approved = !task.approved">{{task.taskNumber}}</div>
</div>
</div>
</md-list-item>
</md-list>
TS:
export class App {
testData: Element[];
constructor() { }
ngOnInit() {
this.testData = [];
for(var i=0; i<90; i++) {
this.testData.push({
id: i,
firstName: "John" + (i + 1),
lastName: "Doe",
tasks: Task[],
});
for(var t=0; t<10; t++) {
this.testData[i].tasks.push(
{
taskNumber: t+1,
approved: (t%2 == 0) ? true: false //for variation sake
}
);
}
}
}
}
export interface Element {
id: number;
firstName: string;
lastName: string;
tasks: Task[];
}
export interface Task {
taskNumber: number;
approved: boolean;
}
After this I tried:
- changing the Detection Strategy to onPush.
- adding a button which adds the listeners to the according row after you click it
- having only one listener and using the information from $event.target
- using pure CSS for handling click events and changing the color with this hack: Can I have an onclick effect in CSS?
None of these made a noticeable improvement on the performance. I could also restrict the number of list items, but surely there is a different way of doing this.