【问题标题】:Angular - Prevent click event on disabled buttonsAngular - 防止禁用按钮上的点击事件
【发布时间】:2020-02-20 02:00:31
【问题描述】:

我试图阻止禁用按钮上的点击事件,换句话说,阻止某些删除禁用属性的用户调用某些操作。

目前,我有以下代码来执行此操作:

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

  // ...
}

有效,但这不是一个好的解决方案,因为我必须为我的应用程序中的所有按钮都这样做(相信我,很容易忘记这样做,甚至 Linter 也可以'在这里帮不了我)。

寻找更强大的解决方案,我认为directive 可以帮助我:

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');
}

...但是它完全没有任何作用。它不会阻止click 事件。是否有任何解决方案我不必在其调用中控制操作本身?

STACKBLITZ

【问题讨论】:

  • dev_054 我的回答有帮助吗?

标签: html angular typescript dom-events


【解决方案1】:

这是一种使用 CSS 的解决方法,比脚本便宜。

你可以轻松使用

pointer-events: none;

在这种情况下,按钮将不可点击。

作为 UX 增强,您还可以将按钮包装在 div 中,并为该 div 赋予 CSS 属性

cursor: not-allowed;

悬停时将显示被阻止的圆圈图标而不是正常的鼠标视图。

【讨论】:

【解决方案2】:

防止禁用按钮上的点击事件

如果有disabled 属性,则不会发生点击。

当用户决定使用 devtools 时

但是,如果用户编辑 HTML 并手动删除 disabled 属性,则会发生单击。您可以尝试按照您的建议进行检查,但浏览器是一个不安全的环境。用户仍然可以代表网页上执行任何代码,而不管您可能进行的任何前端检查。

【讨论】:

  • 嘿@basarat,是的,我知道click 不会被disabled 按钮触发,如果你不使用devtools,但是OP 就是关于它的。我正在寻找与我提出的不同的解决方案。我不想在每个组件上控制它。如果问题不清楚,请告诉我。
  • 这是对的,这就是为什么必须在api中控制。
【解决方案3】:

在你的指令中,你可以做这样的事情。您可以通过在捕获阶段向父级添加事件侦听器来实现。

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

可以在onDestroy中移除监听器

【讨论】:

  • 感谢您的回答,这是一个有趣的解决方案,但是它会阻止对父级的任何点击,甚至是带有click 的 div。示例:stackblitz.com/edit/angular-yonrls
  • 是的,明白了,但是如果您可以将按钮包装在 div 或任何其他标签中。这将解决问题。
  • 用一种更理智的方式更新了答案,以检查 targe 是否为 BUTTON。
猜你喜欢
  • 2018-07-08
  • 2014-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多