Skip to content

Commit eaf6a3d

Browse files
committed
fix(material/autocomplete): add support for initial value in form control
Currently, when we have some initial value in formcontrol those are not marked as selected, this fix will check the initial value and if its matched, will be marked as selected. Fixes angular#29422
1 parent 4e0ea8e commit eaf6a3d

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

src/material/autocomplete/autocomplete-trigger.ts

+13
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ export class MatAutocompleteTrigger
219219
this._canOpenOnNextFocus = this.panelOpen || !this._hasFocus();
220220
};
221221

222+
/** Value of the autocomplete control. */
223+
private _value: any;
224+
222225
/** `View -> model callback called when value changes` */
223226
_onChange: (value: any) => void = () => {};
224227

@@ -265,6 +268,15 @@ export class MatAutocompleteTrigger
265268
ngAfterViewInit() {
266269
this._initialized.next();
267270
this._initialized.complete();
271+
if (this._value) {
272+
const selectedOption = this.autocomplete?.options?.find(
273+
o => this._getDisplayValue(o.value) === this._getDisplayValue(this._value),
274+
);
275+
if (selectedOption && !selectedOption.selected) {
276+
selectedOption.select(false);
277+
this._changeDetectorRef.detectChanges();
278+
}
279+
}
268280
this._cleanupWindowBlur = this._renderer.listen('window', 'blur', this._windowBlurHandler);
269281
}
270282

@@ -447,6 +459,7 @@ export class MatAutocompleteTrigger
447459

448460
// Implemented as part of ControlValueAccessor.
449461
writeValue(value: any): void {
462+
this._value = value;
450463
Promise.resolve(null).then(() => this._assignOptionValue(value));
451464
}
452465

src/material/autocomplete/autocomplete.spec.ts

+55
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,36 @@ describe('MatAutocomplete', () => {
16171617
});
16181618
});
16191619

1620+
describe('form control with initial value', () => {
1621+
let fixture: ComponentFixture<FormControlWithInitialValue>;
1622+
let input: HTMLInputElement;
1623+
1624+
beforeEach(waitForAsync(async () => {
1625+
fixture = createComponent(FormControlWithInitialValue);
1626+
fixture.detectChanges();
1627+
1628+
input = fixture.debugElement.query(By.css('input'))!.nativeElement;
1629+
1630+
fixture.componentInstance.trigger.openPanel();
1631+
fixture.detectChanges();
1632+
await new Promise(r => setTimeout(r));
1633+
}));
1634+
1635+
it('should mark the initial value as selected if its present', fakeAsync(() => {
1636+
const trigger = fixture.componentInstance.trigger;
1637+
trigger.openPanel();
1638+
fixture.detectChanges();
1639+
1640+
const options = overlayContainerElement.querySelectorAll(
1641+
'mat-option',
1642+
) as NodeListOf<HTMLElement>;
1643+
1644+
expect(input.value).toBe('Three');
1645+
expect(options.length).toBe(3);
1646+
expect(options[2].classList).toContain('mdc-list-item--selected');
1647+
}));
1648+
});
1649+
16201650
describe('option groups', () => {
16211651
let DOWN_ARROW_EVENT: KeyboardEvent;
16221652
let UP_ARROW_EVENT: KeyboardEvent;
@@ -4375,6 +4405,31 @@ class PlainAutocompleteInputWithFormControl {
43754405
formControl = new FormControl('');
43764406
}
43774407

4408+
@Component({
4409+
template: `
4410+
<mat-form-field>
4411+
<input matInput placeholder="Choose" [matAutocomplete]="auto" [formControl]="optionCtrl">
4412+
</mat-form-field>
4413+
<mat-autocomplete #auto="matAutocomplete" >
4414+
@for (option of options; track option) {
4415+
<mat-option [value]="option">
4416+
{{option}}
4417+
</mat-option>
4418+
}
4419+
</mat-autocomplete>
4420+
`,
4421+
standalone: false,
4422+
})
4423+
class FormControlWithInitialValue {
4424+
optionCtrl = new FormControl('Three');
4425+
filteredOptions: Observable<any>;
4426+
options = ['One', 'Two', 'Three'];
4427+
4428+
@ViewChild(MatAutocompleteTrigger) trigger: MatAutocompleteTrigger;
4429+
4430+
constructor() {}
4431+
}
4432+
43784433
@Component({
43794434
template: `
43804435
<mat-form-field>

0 commit comments

Comments
 (0)