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.
