Angular Material Autocomplete observable fires additional time after selecting dropdown option
Your issue is occurring because the dropdown selection changes the value of the searchTerm
form control; thus emitting an event for the valueChanges
observable on that form control.
There are a few ways to build some logic into your valueChanges
observable on the form control in order to ignore this unwanted Http GET request.
Naive solution
The naive solution is to store the dropdown option selection value and skip the observable logic if the selectionValue === searchTerm.value
.
var optionSelection; // set this value on selection of a dropdown optionthis.searchTerm.valueChanges .debounceTime(400) .subscribe(data => { if (optionSelection !== searchTerm.value) { this.service.search_word(data).subscribe(response =>{ this.searchResult = response }) } })
Better Solution
The FormControl class has a setValue
function, which has an optional parameter to specify whether or not to emit an event to the valueChanges
observable.
setValue(value: any, options: { onlySelf?: boolean; emitEvent?: boolean; emitModelToViewChange?: boolean; emitViewToModelChange?: boolean;} = {}): void
By changing your dropdown option selection to set the searchTerm form control value with setValue
, you can pass the optional emitEvent: false
parameter and stop this additional observable event from emitting.
searchTerm.setValue(dropdownValue, { emitEvent: false });
If emitEvent is false, this change will cause a valueChanges event on the FormControl to not be emitted. This defaults to true (as it falls through to updateValueAndValidity).
The problem lies in the amount of event that are tiggered there are two... I already made a bug for it's but it's how it supposed to work. Hope this will help.
This is my solution:
Html:
<mat-option *ngFor="let item of searchResult" [value]="item.Id" (onSelectionChange)="onSelectionChange($event, item.Id)"> // or item
In your component:
private onSelectionChange(_event: any, _id: any) { if (_event.isUserInput === true) { // there are two events one with true and one with false; this.service.search_word(_id).subscribe(response =>{ this.searchResult = response })}
you can use (keyup)="onKeyUp($event)"
in your input text and you can use it like this
onKeyUp(event: any) { this.service.search_word(event.target.value).subscribe(response =>{ this.searchResult = response })}