bug(MAT-AUTOCOMPLETE): on option select on chrome android 13, dropdown collapses without selection
Is this a regression?
- [ ] Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
No response
Description
I have am having a bit of an issue with a mat-autocomplete.
I have deployed the code base from https://stackblitz.com/run?file=src%2Fexample%2Fautocomplete-require-selection-example.html&startScript=start to http://resparke-indigo-backup.s3-website-ap-southeast-2.amazonaws.com/ so I can test it on my Android 13 device.
On Android 10, IOS Safari 17, 18 etc, macbook Chrome, it all works good.
But not on Android 13' Chrome.
What I can find from debugging is that when I click it sometimes doesnt select a value but just collapses the soft keyboard.
I created a recording with onclick debug output so you can see which element is clicked:
I am not sure how to debug this, because the example I am using is pure and simple and 100% from angular mat website. I think the issues is related to the softkeyboard closing which does something with the overlay.
Reproduction
As mentioned above, the stackblitz example is deployed on https://app-test.resparke.com but you would have to run it on an Android 13 tablet , Chrome, with a soft keyboard and see this issue happening
Expected Behavior
When option is selected, I expect that selection to be recorded.
Actual Behavior
When I open the test app on http://resparke-indigo-backup.s3-website-ap-southeast-2.amazonaws.com/, and I click on the formfield, the dropdown appears and the softkeyboard opens, I select option 2. The soft keyboard closes and no option is selected. When I click again on the formfield, the dropdown appears again and now I can select and option. That seems to be a consistent behaviour on Android 13/Chrome.
Environment
- Angular: 20.3.x
- CDK/Material: 202.2.12
- Browser(s): Chrome
- Operating System (e.g. Windows, macOS, Ubuntu): Android 13
Further investigation:
Chatgpt suggested to cancel all events on the mat-option:
<mat-option [value]="option.value"
(mousedown)="$event.preventDefault()"
(touchstart)="$event.preventDefault()"
(pointerdown)="$event.preventDefault()">
{{option.viewValue}}
</mat-option>
which does make the autocomplete select the value on Android 13, but it no longer selects any value on other browsers which work with default code. This because all events are cancelled and I probably have to handle the select now manually.
Apparently I should only cancel mousedown:
<mat-option [value]="option.value"
(mousedown)="$event.preventDefault()"
>
Selection now works for all browsers but keyboard doesnt close, so I have to handle this manually.
Overall, I do think there is a bug in the mat-autocomplete how it handles the option select in conjunction with they keyboard close event on Android 13.
My working code is:
<div class="flex flex-col">
<mat-form-field [appearance]="appearance" [attr.appearance]="appearance" [subscriptSizing]="subscriptSizing">
<input
#input
type="text"
matInput
[placeholder]="placeholder"
[formControl]="control"
[matAutocomplete]="auto"
(input)="filter()"
(focus)="filter()"
>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn.bind(this)">
@for (option of filteredOptions; track option.value) {
<mat-option [value]="option.value"
(mousedown)="$event.preventDefault()"
(click)="selectOption(option)"
>
{{option.viewValue}}
</mat-option>
}
</mat-autocomplete>
<mat-icon matSuffix (click)="iconClick()">{{ icon }}</mat-icon>
@if (!hideErrorMessage) {
<mat-error>{{ getErrorMessages() }}</mat-error>
}
</mat-form-field>
</div>
import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { ViewValue } from '@resparke/models';
import { getErrorMessages } from '@resparke/utils/form';
import { requireMatch } from '../../validators';
@Component({
selector: 'app-autocomplete',
standalone: true,
imports: [ReactiveFormsModule, MatAutocompleteModule, MatFormFieldModule, MatInputModule, MatIconModule],
templateUrl: './autocomplete.component.html',
styleUrls: ['./autocomplete.component.scss']
})
export class AutocompleteComponent implements OnInit {
@ViewChild(MatAutocompleteTrigger) trigger!: MatAutocompleteTrigger;
@ViewChild('input') input: ElementRef<HTMLInputElement>;
@Input() options: ViewValue[];
@Input() control: FormControl;
@Input() creatable = false;
@Input() icon = 'search';
@Input() resetOnIconClick = false;
@Input() hideErrorMessage: boolean = false;
@Input() appearance: 'outline' | 'fill' = 'outline';
@Input() subscriptSizing: 'fixed' | 'dynamic' = 'fixed';
@Input() placeholder: string;
filteredOptions: ViewValue[];
getErrorMessages = () => getErrorMessages(this.control);
ngOnInit(): void {
this.filteredOptions = this.options.slice();
if (!this.creatable) {
// check if input matches the options list provided
this.control.addValidators(requireMatch(this.options))
}
}
selectOption(e: any) {
this.trigger?.closePanel();
// defer blur so selection finishes cleanly
setTimeout(() => this.input.nativeElement.blur(), 0);
}
filter(): void {
const filterValue = this.input.nativeElement.value.toLowerCase();
this.filteredOptions = this.options.filter(o => o.viewValue.toLowerCase().includes(filterValue));
}
displayFn(value?: string) {
const match = this.options.find(_ => _.value === value);
return match ? match.viewValue : undefined;
}
iconClick() {
if (this.resetOnIconClick) {
this.control.reset();
}
}
}
So the selectOption was necessary to close the softkeyboard. I tried using optionSelected but that was not emitting any value.
And the (mousedown)="$event.preventDefault()" on the mat-option helps selecting a value on Android 13 Chrome.
I hope my investigation and problem solving allows for a fix in mat-autocomplete code so that I dont have to do these hacks?
@adolgachev hi, is this something that can be resolved easily so I don't have to do anything extra in my code to resolve the issue?