Search code examples
angularangular-materialmat-form-fieldmat-input

How to prevent matInput from focusing when clicking on matPrefix/matSuffix?


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?


Solution

  • 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();
      }