I am having an issue when trying to programmatically select an option in an autocomplete.
MatAutocomplete
has no select method, so I tried using the select method on the MatOption. This does not appear to do anything.
matAutocomplete.options.find(opt => opt.id === 1).select();
Using the Autocompelete _emitSelectEvent(option) method results in firing the optionSelected method but does not update the UI or actually set the option to be selected.
matAutocomplete._emitSelectEvent(option);
Is there a way to programmatically select an option so that it updates the UI and calls the optionSelected event emitter?
<input [matAutocomplete]="autocomplete1" />
<mat-autocomplete #autocomplete1="matAutocomplete" [displayWith]="display1()" (optionSelected)="selected1($event.option.value)">
<mat-option *ngFor=let opt of filteredOptions | async" [value]="opt">
{{ opt.name }}
</mat-option>
</mat-autocomplete>
<input [matAutocomplete]="autocomplete2" />
<mat-autocomplete #autocomplete2="matAutocomplete" [displayWith]="display2()" (optionSelected)="selected2($event.option.value)">
<mat-option *ngFor="let opt of filteredOptions2 | async" [value]=opt>
{{ opt.name }}
</mat-option>
</mat-autocomplete>
export class obj {
public id: number;
public name: string;
}
@ViewChild("autocomplete2") autocomplete2: MatAutocomplete;
selected1(value: obj): void {
const opt = this.autocomplete2.options.find(opt => (opt.value as obj).id === 1);
// Does nothing
opt.select();
// Fires optionSelected on autocomplete2, does not update the UI
opt._selectViaInteraction();
// Fires optionSelected on autocomplete2,
// does not set the option to be selected or update the UI
this.autocomplete2._emitSelectEvent(opt);
}
I am using Angular & Material version 5.2.4
I was able to solve this issue by setting the value of the input2 with the full object that I wanted to select from the second autocomplete.
This would then be displayed in the input using the displayWith
function set in the mat-autocomplete.
<input [matAutocomplete]="autocomplete1" [formControl]="input1" />
<mat-autocomplete #autocomplete1="matAutocomplete" (optionSelected)="selected1($event.option.value) [displayWith]="display1()">
<mat-option *ngFor="let opt of options1" [value]="opt">
{{ opt.name }}
</mat-option>
</mat-autocomplete>
<input [matAutocomplete]="autocomplete2" [formControl]="input2" />
<mat-autocomplete #autocomplete2="matAutocomplete" (optionSelected)="selected2($event.option.value) [displayWith]="display2()">
<mat-option *ngFor="let opt of options2" [value]="opt">
{{ opt.name }}
</mat-option>
</mat-autocomplete>
export class Obj {
public id: number;
public name: string;
}
let randomObj: Obj = new Obj();
input2: FormControl = new FormControl();
select1(value: Obj): void {
this.input2.setValue(this.randomObj);
}
You do not need to go into the autocomplete and get the specific option that you want, you can just set anything to the value that can then be displayed with the displayWith
function.
For example, if you displayWith
function is as follows:
displayWith(value: Obj): string {
return value.name;
}
if you set the value of the input with any object that has a name property then it will display as the text in the input.
input.setValue({ name: "HelloWorld" });
Even though the object passed into the setValue method is not of the type Obj it will still work with the displayWith
function. If you set the value to an object that cannot be displayed using the displayWith
function then all that happens is that the text in the input will be blank (whilst the value of the input is still set to the object set).
so input.setValue({ foo: "bar" })
will display nothing in the textbox but input.value
will be { foo: "bar" }