I'm trying to implement a counter form field. It has two buttons; one for incrementing the count value and one for decrementing it. Implementation has been pretty straightforward so far.
<mat-form-field>
<button matPrefix mat-icon-button (click)="onDecrement()">
<mat-icon svgIcon="remove"></mat-icon>
</button>
<input type="number" matInput [formControl]="counter">
<button matSuffix mat-icon-button (click)="onIncrement()">
<mat-icon svgIcon="add"></mat-icon>
</button>
<mat-error *ngIf="counter.errors?.['min']">...</mat-error>
</mat-form-field>
However, when I click on the matSuffix
increment button for example, the matInput
is automatically getting focused. This triggers the keyboard to slide up on mobile browsers, and frustrate users as the viewport jitters up with it. How do I prevent this behavior?
I tried making a custom directive to apply to the buttons but to no avail. I also tried implementing the counter as a custom MatFormFieldControl
, but it has its own problems, so that approach is a no-go.
The only resource I can find related to my concern is this GitHub issue. According to it, I should bind $event
onto the onDecrement()
and onIncrement()
methods, and then call .stopPropagation()
on the bound event object. It worked! No more keyboard showing up when pressing the increment and decrement button.
My only problem with that approach is that, now the mat-error
message doesn't show up when the counter
value is below the minimum Validators.min
constraint. So the "solution" presented in the GitHub discussion is really a broken accessibility issue for my use case.
How do I prevent matInput
from gaining focus when pressing/clicking on matPrefix
and matSuffix
within mat-form-field
, without compromising on the accessibility issue stated above?
when you use
input.value = '';
The only you make is change the DOM (but not the value of the control)
As the error is only showed if the "FormControl" is touched, futhermore give value using setValue, you should markAsTouched it "manually"
onDecrement(evt:any){
this.counter.setValue((+this.counter.value)-1)
this.counter.markAsTouched()
evt.stopPropagation();
}
onIncrement(evt:any){
this.counter.setValue((+this.counter.value)+1)
this.counter.markAsTouched()
evt.stopPropagation();
}