html - Angular - Forhindre klikkhendelse på deaktiverte knapper


Jeg prøver å forhindre klikkhendelser på deaktiverte knapper, med andre ord, å forhindre at en bruker som fjerner attributtet 'disabled' kan utføre en handling.

Foreløpig har jeg følgende kode for å gjøre dette:

<button [disabled]="someCondition" (click)="executeAction()">Execute action</button>
executeAction(): void {
  if (this.someCondition) return;

  // ...
}

Fungerer, men det er ikke en god løsning siden jeg må gjøre det for ALLE knappene i appen min (og tro meg, det er lett å glemme å gjøre dette og til og med en Linter kan ikke hjelpe meg her).

På jakt etter en mer robust løsning, tenkte jeg at directive kunne hjelpe meg:

import { Directive, HostListener, Input, Renderer2, ElementRef } from '@angular/core';

@Directive({
  selector: 'button'
})
export class ButtonDirective {
  @Input() set disabled(value: boolean) {
    this._disabled = value != null;
    this.renderer2.setAttribute(this.elementRef.nativeElement, 'disabled', `${this._disabled}`);
  }

  private _disabled: boolean;

  constructor(
    private readonly elementRef: ElementRef,
    private readonly renderer2: Renderer2
  ) { }

  @HostListener('click', ['$event'])
  onClick(mouseEvent: MouseEvent) {
    // nothing here does what I'm expecting
    if (this._disabled) {
      mouseEvent.preventDefault();
      mouseEvent.stopImmediatePropagation();
      mouseEvent.stopPropagation();

      return false; // just for test
    }
  }
}
<button [disabled]="someCondition" (click)="executeAction()">Execute action</button>
executeAction(): void {
  console.log('still being called');
}

...men det gjør absolutt ingenting. Det forhindrer ikke click-hendelsen. Finnes det noen løsning der jeg ikke må kontrollere handlingen selv i kallet?

STACKBLITZ

Svar #1

Dette er en løsning med CSS som er billigere enn skript.

Du kunne lett bruke

pointer-events: none;

I dette tilfellet vil ikke knappen være klikkbar.

Som en UX-forbedring kunne du også pakke knappen din inn i en div og gi denne div-en en CSS-egenskap

cursor: not-allowed;

Som vil vise det blokkerte sirkelikonet i stedet for det vanlige museikonet når man holder musepekeren over.

Svar #2

I direktivet ditt kan du gjøre noe som dette. Du kan oppnå det ved å legge til en hendelseslytter på forelderen i fangstfasen.

ngOnInit() {
    this.elementRef.nativeElement.parentElement.addEventListener('click',(e) => {
      if(this._disabled && e.target.tagName === 'BUTTON') {
        e.stopImmediatePropagation();
        e.stopPropagation();
      }
    }, true);
  }

Du kan fjerne lytteren i onDestroy

Relaterte artikler