0
votes

Currently i´m working in application where i need to filter an array of items, the filters need to be persistent, i save the filters and when i get the filters back i need to check which filters are active or not and change the check state of the checkbox.

enter image description here

for this im using a function existInArray(element, array): boolean that check is the filter is in the array of filters and return true or false

Check is filter is active

  public existInArray(element, array: Array<string>): boolean {
    if (!element) {
      return;
    }
    return array.indexOf(element.toString()) > -1;
  }

Checkbox template

<div class="filter-list-container m-top">
      <div *ngFor="let assignment of (filterService.getFilter(filterType.FILTER_ASSIGNMENT).items.ToArray() | filterQuery: filterOptions.assignments | sortBy: configService.config.sortUserBy:'assignment')">
         <mat-checkbox [checked]="existInArray(assignment.id, filterService.filterAssignment)"
            [ngClass]="{ 'checkbox-ie': platform.TRIDENT }"
            (change)="filterBy(filterType.FILTER_ASSIGNMENT, assignment.id, filterService.filterAssignment, assignment.name)"
            [value]="assignment.id">
             <div class="assigned">
               <user-image [inline]="true" [user]="assignment.assignment"></user-image>
                <p class="assigned-name">{{ assignment.name }}</p>
              </div>
            </mat-checkbox>
           </div>
          </div>

Now the function is working just fine, there is no error, but there is problem here, and is because of the angular change detection, the function is been call more than 1000 times, so i was thinking in maybe use a pipe but for some reason it did not work, any idea in which other way can i do this or maybe a way to optimize ( just in case i´m using angular material for the checkbox components ).

1
Note: You can use Array.prototype.includes instead of checking if Array.prototype.indexOf is more than -1. - Edric
In this case it will the same, the function it will executing more than 1000 times because of the changeDetection from angular - Miguel Frias
try adding some metadata to assignment, e.g. assignment.__checked__ = existInArray(....) computed only when underlying data changes. and in html, [checked]="assignment.__checked__ " - ABOS

1 Answers

0
votes

Fix the problem, a pipe is the best way to do it, but because a pipe is only call when there is change in the value i need to pass a value that is gonna changing when there is a new filter in the filter array, so in this case i pass the length of the filter array

Pipe

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  // tslint:disable-next-line:pipe-naming
  name: 'checkActiveCheckbox'
})
export class CheckActiveFilterPipe implements PipeTransform {
  transform(value: any, arg?: Array<any>, change?: any): any {
    console.count('Filter PIPE');
    if (!value) {
      return;
    }
    return arg.indexOf(value.toString()) > -1;
  }
}

Template

    <div class="filter-list-container m-top">
      <div
        *ngFor="let assignment of (filterService.getFilter(filterType.FILTER_ASSIGNMENT).items.ToArray() | filterQuery: filterOptions.assignments | sortBy: configService.config.sortUserBy:'assignment')">
        <mat-checkbox
          [checked]="assignment.id | checkActiveCheckbox:filterService.filterAssignment:filterService.filterAssignment.length"
          [ngClass]="{ 'checkbox-ie': platform.TRIDENT }"
          (change)="filterBy(filterType.FILTER_ASSIGNMENT, assignment.id, filterService.filterAssignment, assignment.name)"
          [value]="assignment.id">
          <div class="assigned">
            <user-image [inline]="true" [user]="assignment.assignment"></user-image>
            <p class="assigned-name">{{ assignment.name }}</p>
          </div>
        </mat-checkbox>
      </div>
    </div>