Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

method gets called multiple times in angular material autocomplete

We have created a component using Angular material's autocomplete. To display the options, we are traversing through an array of 51 objects. I am applying a CSS class to the already selected option. The isAccountingTypeSelected method determines whether the option was selected or not. The method gets called 51*28 = 1428 times. I don't seem to understand the reason? It should only be called 51 times, shouldn't it?

<mat-form-field class="full-width">
  <input type="text" matInput #autoCompleteInput [formControl]="autocompleteForm" [matAutocomplete]="auto" placeholder="Choose Accounting Type" aria-label="Number">

  <span matSuffix class="close-icon hover" *ngIf="autoCompleteInput.value" (click)="clearAll($event)"></span>
  <span matSuffix class="arrow-drop-down-icon hover" (click)="openPanel()"></span>

  <mat-autocomplete #auto="matAutocomplete" (optionSelected)="accountingTypeSelected($event)">
    <mat-option *ngFor="let accountingType of filteredAccountingTypes | async" [value]="accountingType.code">
      <span class="accounting-type-options" [class.selected]="isAccountingTypeSelected(accountingType.code)">
        {{ accountingType.name + ' (' + accountingType.code + ')' }}
      </span>
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

isAccountingTypeSelected(code: string): boolean {
  console.log('I was called');
  if (this.selectedAccountingTypes.find((accountingType: AccountingType) => accountingType.code === code)) {
    return true;
  }

  return false;
}
like image 506
Pritam Bohra Avatar asked Sep 09 '19 15:09

Pritam Bohra


People also ask

Why is Onselectionchange called twice?

The onSelectionChanged event is called twice in the dxSelectBox if it has been initialized with a value | DevExpress Support.

What does autocomplete do in angular?

The Angular Autocomplete is a textbox or search box component that provides a list of suggestions to select from as the user types. It has several out-of-the-box features such as data binding, filtering, grouping, autocomplete search, UI customization, accessibility, and more.

How do you increase the width of an autocomplete mat?

mat-autocomplete styles are inherited from cdk-overlay-pane. In order to change width use below CSS. width: auto ! important; works a little better than min-width since it won't make the overlay large if it doesn't need to.


3 Answers

Angular uses changedetection lifecycle multiple times to check if the function has changed for [class.selected] or ngClass. If you use function, it will call multiple times. For this reason the use of function is not advised when you bind, instead you should calculate the values in your component.ts file and just bind the values to ngClass or [class].

Example: Stackblitz

N.B: We know when we change selected value it triggers a event change, we can calculate it and attach the calculation result to the [class.my-class] or ngClass.

like image 150
Md Rafee Avatar answered Oct 20 '22 10:10

Md Rafee


Angular is gonna evaluate that expression every time it checks for changes, which in your case might be the css being added to your span elements. Calling methods from the template in a for loop is not the best approach because they are called very often. You should instead store the result in a property and bind to this property instead.

like image 45
Tiago Silva Avatar answered Oct 20 '22 10:10

Tiago Silva


It is a bind problem. Angular checks more times the result value. You can try with ChangeDetectionStrategy.CheckOnce

like image 2
Nicola Avatar answered Oct 20 '22 10:10

Nicola