Reputation: 436
I have successfully implemented mat-autocomplete and it is working fine if selected from auto complete drop down. I am facing issues when i have typed in some text and navigate to other fields without selecting below dropped in auto complete fields. It retains the value typed in autocomplete field.
I have used below approach to fix this issue -
MatAutocompleteTrigger - Below code I have used in ts file -
@ViewChild('autoCompleteInput', { static: false,read: MatAutocompleteTrigger }) trigger: MatAutocompleteTrigger;
.
.
.
this.trigger.panelClosingActions
.subscribe(e => {
if (!(e && e.source)) {
this.accountForm.get('accountId').setValue="";
this.account.accountId = null;
}
})
First of all , i am unable to keep it in any angular life cycle hook. This trigger doesn't get initialized during angular lifecycle hooks, but later while it receives any values form mat-autocomplete.So it clears value as soon I type in text in field(keeping the below autocomplete list; which doesn't look good)
2.Used observalble on filterOptions(Obserable on my autocomplete field) - I have used below code for i t -
this.filteredOptions = this.accountForm.get('accountId').valueChanges.pipe(
debounceTime(250),
distinctUntilChanged(),
filter(searchString => typeof searchString === 'string'),
filter(searchString => searchString.length > 0),
switchMap(searchString => {
return this.accountService.autoCompleteBrokerSearch(searchString);
})
);
this.filteredOptions.takeUntil(this.ngUnsubscribe).subscribe((lookups: accountEntityModel[]) => {
if (lookups.length === 0) {
this.account.accountId = null;
this.accountForm.get('accountId').patchValue('');
}
if(lookups.find(value => value.id !== this.account.id)){
this.account.accountId = null;
this.accountForm.get('accountId').patchValue('');
}
});
with Template code -
<mat-form-field appearance="standard" >
<mat-label>{{ 'account.enterAccount' | translate }}</mat-label>
<input
matInput
formControlName="accountId"
class="search-select"
[matAutocomplete] = "accountAutocomplete"
#autoCompleteInput="matAutocompleteTrigger">
<mat-autocomplete #accountAutocomplete = "matAutocomplete" [displayWith]="displayFn.bind(this)" >
<mat-option [value]="accountOption" *ngFor="let accountOption of filteredOptions | async" (onSelectionChange)="onEnteredAccount(accountOption)" >{{
accountOption.description
}}</mat-option>
</mat-autocomplete>
</mat-form-field>
I only require to clear the field if we have not selected anything from auto complete, and it should clear field values from form too.
Upvotes: 3
Views: 14034
Reputation: 2166
It has been recently introduced to Angular 17 that when you use requireSelection mat-autocomplete field, it only accepts values from the list, otherwise it will be cleared. Example code from the official angular site:
HTML:
<form class="example-form">
<mat-form-field class="example-full-width">
<mat-label>Number</mat-label>
<input #input
type="text"
placeholder="Pick one"
matInput
[formControl]="myControl"
[matAutocomplete]="auto"
(input)="filter()"
(focus)="filter()">
<mat-autocomplete requireSelection #auto="matAutocomplete">
@for (option of filteredOptions; track option) {
<mat-option [value]="option">{{option}}</mat-option>
}
</mat-autocomplete>
</mat-form-field>
</form>
Typescript:
export class AutocompleteRequireSelectionExample {
@ViewChild('input') input: ElementRef<HTMLInputElement>;
myControl = new FormControl('');
options: string[] = ['One', 'Two', 'Three', 'Four', 'Five'];
filteredOptions: string[];
constructor() {
this.filteredOptions = this.options.slice();
}
filter(): void {
const filterValue = this.input.nativeElement.value.toLowerCase();
this.filteredOptions = this.options.filter(o => o.toLowerCase().includes(filterValue));
}
}
Upvotes: 0
Reputation: 961
Its working fine for me..
HTML:
<mat-form-field appearance="outline">
<input type="text" placeholder="start type.." #autoCompleteInput="matAutocompleteTrigger"
matInput [matAutocomplete]="catAuto" [formControl]="selectedData" (keyup)="onChange($event)">
<mat-autocomplete #catAuto="matAutocomplete" [displayWith]="displayFnForAutoComplete"
(optionSelected)="onSelect($event.option.value)">
<mat-option *ngFor="let option of filterList" [title]="option" [value]="option.id">
{{option.name}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
TS:
@ViewChild('autoCompleteInput', { static: false, read: MatAutocompleteTrigger }) trigger: MatAutocompleteTrigger;
selectedData = new FormControl();
ngAfterViewInit() {
this.trigger.panelClosingActions
.subscribe(e => {
this.selectedData.setValue(null);
});
}
Upvotes: 1
Reputation: 1997
You can remove the formControl-binding from your input and when you select an option you set that id to your form.
You are already calling such a function (onSelectionChange)="onEnteredAccount(accountOption)"
in which you can do that.
Upvotes: 0