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
