为什么onSelectionChange被调用两次?

时间:2018-10-26 13:37:03

标签: angular typescript

我正在使用Angular Material自动完成,如下所示:

<mat-autocomplete #autocomplete="matAutocomplete" [displayWith]="displayFn" autoActiveFirstOption>
  <mat-option *ngFor="let option of filteredOptions$ | async" [value]="option" (onSelectionChange)="onSelectionChanged(option)" >
    {{displayFn(option)}}
  </mat-option>
</mat-autocomplete>    

这是处理程序:

onSelectionChanged(option) {
  console.log('Selected ' + option.name);
}

由于某种原因,onSelectionChanged()被调用了两次。第二次使用 old 值!我不明白为什么。这是怎么回事?

先选择项目1,然后选择项目2,再选择项目3:

> Selected item 1
> Selected item 2
> Selected item 1  // The unwanted call with the old value
> Selected item 3
> Selected item 2  // The unwanted call with the old value

8 个答案:

答案 0 :(得分:3)

材料具有optionSelected事件,您可以使用它

<mat-autocomplete #autocomplete="matAutocomplete" (optionSelected)="onSelectionChanged($event)" [displayWith]="displayFn" autoActiveFirstOption>

 <mat-option *ngFor="let option of filteredOptions$ | async" [value]="option" >
{{displayFn(option)}}
 </mat-option>

</mat-autocomplete>  



onSelectionChanged(event) {
   console.log(event.option.value);
}

答案 1 :(得分:2)

只是使用(点击)代替。看一看:

  <mat-autocomplete #auto="matAutocomplete">
    <mat-option
      (click)="selected(entity)"
      *ngFor="let entity of filteredOptions"
      [value]="entity.short"
    >
      {{ entity.short_header}}
    </mat-option>
  </mat-autocomplete>

编辑:如果您使用键盘选择选项,则不会触发此操作。 因此,或者因为您已经使用 [displayWith],该值将是对象。您可以在 mat-autocomplete 元素上使用 (optionSelected) 输出:

<mat-autocomplete (optionSelected)="optionSelected($event)" 
#auto="matAutocomplete" [displayWith]="displayEntity">
    <mat-option *ngFor="let e of filteredEntities$ | async" [value]="e">
        {{ e.short_header }}
    </mat-option>
</mat-autocomplete>

答案 2 :(得分:1)

this issue中所述,这是onSelectionChanged的预期行为。选择更改事件不仅在选择选项时被触发,而且在取消选择时也会被触发。因此,当选择一个选项时,将在该事件以及未选择的任何选项上触发该事件。

尝试改用optionSelected

答案 3 :(得分:0)

您还可以使用(更改)事件

<mat-autocomplete #autocomplete="matAutocomplete" [displayWith]="displayFn" autoActiveFirstOption>
  <mat-option *ngFor="let option of filteredOptions$ | async" [value]="option" (change)="onSelectionChanged(option)" >
    {{displayFn(option)}}
  </mat-option>
</mat-autocomplete>  

答案 4 :(得分:0)

您可以检查事件是否由用户触发,如下所示:

onSelectionChanged(option) {
   if(option.isUserInput==true){
      console.log('Selected ' + option.name);
   }
}

答案 5 :(得分:0)

我在mat-select内遇到mat-option的相同问题,并通过以下方式解决:

模板

<mat-select>
 <mat-option (onSelectionChange)="handleMetaSignalChange(metaSignal.name,$event);" *ngFor="let metaSignal of metaSignals" [value]="metaSignal">
  {{ metaSignal.name }}
 </mat-option>
</mat-select>

代码

 handleMetaSignalChange(metaSignal: string, event: any) {
    if (event.isUserInput) {    // ignore on deselection of the previous option
      console.log('Meta Signal Changed to ' + metaSignal + event.isUserInput);
    }
 }

答案 6 :(得分:0)

您可以使用以下方法对其进行修复:

  1. 材料方式:

<mat-select [(ngModel)]="selectedLanguage" (ngModelChange)="onLangChange($event)">
                                            <mat-option *ngFor="let language of languages" [value]="language">
                                                {{language}}
                                            </mat-option>
                                        </mat-select>    
  1. 传统方式:

   <select [(ngModel)]="status" (ngModelChange)="onChangeStatus($event)"
                                                [ngModelOptions]="{standalone: true}"
                                                class="form-control custom-select" id="status">
                                                <option i18n value="All" selected>Statut</option>
                                                <option i18n value="Yes">Visible</option>
                                                <option i18n value="No">Non Visible</option>
                                            </select>    

在您的组件ts文件中:

onChangeStatus(event) {
    if (event === "All") {
      this.status = ...
    }
    else
     ...
}

答案 7 :(得分:-1)

changeDegree(event) {
    if (event.isUserInput) { 
      console.log(event.source.value);

      this._degreeArray.length = 0;
      this.changeDegreeDetails(event.source.value.id);
    }
  }