角度组件:禁用点击事件

时间:2019-03-28 16:17:10

标签: angular angular-components

我正在创建一个像这样的可重用组件:

<my-button [isDisabled]="isDisabled" (click)="click($event)"> submit </my-button>

当属性isDisabled为true时,我想禁用click事件,我尝试过类似的操作,但是它不起作用。

packages / component / my-button.component.html

<button  [disabled]="isDisabled" #myButton>
        <ng-content></ng-content>
</button>

packages / component / my-button.component.ts

@ViewChild('uxButton') uxButton: ElementRef;
@Input() isDisabled: boolean = false;

this.myButton.nativeElement.parentNode.removeEventListener('click' , (e) => {
       e.stopPropagation();
});

9 个答案:

答案 0 :(得分:2)

尝试这样

<button  [disabled]="isDisabled" (click)="btnClick.emit($event)">
        <ng-content></ng-content>
</button>

@Input() isDisabled: boolean = false;
@Output() btnClick = new EventEmitter();

使用Output,并且默认情况下,如果按钮被禁用,则按钮单击事件将不起作用。利用它

<my-button [isDisabled]="isDisabled" (btnClick)="click($event)"> submit </my-button>

答案 1 :(得分:1)

以下CSS也可以解决此问题:

library(shinydashboard)
library(shiny)

sidebar <- dashboardSidebar(
  tags$head(tags$style(
    HTML('.content-wrapper { height: 1500px !important;}')
  )),
  hr(),
  sidebarMenu(
    id = "tabs",
    menuItem(
      "a1",
      tabName = "principal",
      icon = icon("pagelines"),
      selected = TRUE
    ),
    menuItem(
      "a2",
      icon = icon("chart-bar"),
      menuSubItem("b1", tabName = "identificacion", icon = icon("angle-right")),
      menuSubItem("b2", tabName = "comunicacion", icon = icon("angle-right")),
      menuSubItem("b3", tabName = "medicamentos", icon = icon("angle-right")),
      menuSubItem("b4", tabName = "cirugias", icon = icon("angle-right")),
      menuSubItem("b5", tabName = "infecciones", icon = icon("angle-right")),
      menuSubItem("b6", tabName = "caidas", icon = icon("angle-right"))
    ),
    menuItem("a3", tabName = "procesos", icon = icon("chart-bar")),
    menuItem("a4", tabName = "tiempos", icon = icon("chart-bar")),
    menuItem("a5", tabName = "manual", icon = icon("mortar-board")),
    menuItem("a6", tabName = "acerca", icon = icon("question"))
  ),
  width = 285,
  hr(),
  conditionalPanel("input.tabs=='identificacion'",
                   fluidRow(
                     column(1),
                     column(
                       10,
                       menuItem(
                         "c1",
                         tabName = "admision_iden",
                         icon = icon("chart-line"),
                         selected = FALSE
                       ),
                       menuItem(
                         "c8",
                         tabName = "uci_iden",
                         icon = icon("chart-line"),
                         selected = FALSE
                       )
                     )
                   ))
)

body <- dashboardBody(tabItems(
  tabItem(tabName = "principal",
          withMathJax(), ("example of text")),

  tabItem(tabName = "admision_iden", titlePanel("example1"), "example of text 2"),

  tabItem(tabName = "uci_iden", titlePanel("example 2"), "example of text 3")
))

ui <- dashboardPage(dashboardHeader(title = "Indic", titleWidth = 285),
                    sidebar,
                    body)

server <- function(input, output) {}

runApp(list(ui = ui, server = server))

现在您不必像其他答案中那样手动传递click事件:您有旧的(click)事件返回:D

# This prevents host to get a direct click
:host {
  pointer-events: none;
}

# This prevents the span inside the button to "steal" the click from the button
:host /deep/ button span {
  pointer-events: none;
}

# Now only the button can get a click 
# Button is the only smart enough to stop propagation when needed
button {
  pointer-events: auto;
}

在您的自定义组件中,您只需传递禁用的属性:

<my-button [isDisabled]="isDisabled" (click)="click($event)"> submit </my-button>

还要考虑将stackblitz修改为another stackoverflow answer

答案 2 :(得分:1)

我能够在 scss 中禁用禁用按钮的点击事件。这是我添加的

:host {
button {
&:disabled:active {
      pointer-events: none;
}
}
}

答案 3 :(得分:0)

我们可以根据需要使用ElementRef / HostListener添加eventlistener / remove,但是下面是简单的解决方法。

click(event) {
if (this.isDisabled) {
return;
}
......
}

答案 4 :(得分:0)

我认为问题出在您的代码中:

<my-button [isDisabled]="isDisabled" (click)="click($event)"> submit </my-button>

应该是

<my-button [disabled]="isDisabled" (click)="click($event)"> submit </my-button>

答案 5 :(得分:0)

您应该使用documentation中提到的[disabled]属性:

<button [disabled]="isDisabled" (click)="disableButton()">Disable button</button>

然后在您的代码中

export class AppComponent  {
  isDisabled = false;

  disableButton() {
    this.isDisabled = true;
    // your code...
  }
}

查看StackBlitz进行演示。

答案 6 :(得分:0)

您可以在(click)属性上进行检查:

<my-button [isDisabled]="isDisabled" (click)="!isDisabled && click($event)"> submit </my-button>

答案 7 :(得分:0)

首先,当我们已经拥有本地按钮组件时,我们需要问自己为什么要创建一种新型的按钮组件。可能是这样的:

  • 利用一些Angular助手,例如动画
  • 在执行某些点击处理程序期间禁用按钮。
  • 进度指示。
  • ...

如果可以使用本地按钮(解决方案0 )解决要求,请坚持执行。否则,继续。

在创建可重用之前我们需要了解的两个重要事项 按钮组件:

K1 只能禁用一部分HTML元素, https://html.spec.whatwg.org/multipage/semantics-other.html#disabled-elements。这个 表示即使禁用了元素,也会触发点击处理程序。

K2 在Angular中,外部事件无法从内部进行控制 内。 https://github.com/angular/angular/issues/12630

解决方案1.单击处理程序作为输入

要解决K2,您可以使用@Input回调而不是 事件绑定。然后,您可以从内部控制它,并且 您甚至可以访问内部的回调结果。它 看起来像:

<my-button [myClick]="doIt"> or with arguments <my-button [myClick]="doIt.bind(1)">

@HostListener('click') onClick(event) {
  this.myClick();
}

由于您已完全控制了回调,因此可以省略调用 disabled时使用它。

该解决方案急需解决的问题是带有进度指示的按钮。当您完全控制了回调时,库按钮可以启动/停止进度条的动画,甚至可以通过在执行过程中禁用它来阻止其他点击。将其与本模块中的进度按钮进行比较 https://github.com/michaeldoye/mat-progress-buttons,您需要在哪里 为按钮的每个实例启动/停止动画!

缺点:非标准外观。您的图书馆用户会喜欢为什么 回调输入而不是事件绑定...

解决方案2。CSS

您可以尝试使用CSS pointer-events:none解决K1。它 会在表面上起作用,阻止用户鼠标触发点击 事件。但是,您仍然可以实用地单击 按钮。当按钮“禁用”时,myButton.click()仍会触发。

缺点:“禁用”元素仍然可以click使用。可能不适合 您的图书馆用户编写自动化测试。

解决方案3.组件化本机按钮

要使禁用和事件按预期运行,您需要应用 组件直接放在HTML按钮元素上。在Angular Material中看起来 像<button mat-button>https://github.com/angular/components/blob/master/src/material/button/button.ts#L66

这很简单:

@Component({
  selector: 'button[my-button]',
  template: '<ng-content></ng-content>'
})

并使用它:

<button my-button (click)="doIt()" [disabled]="isDisabled">Save</button>

现在,my-button被禁用时,不会触发click事件。

缺点:本地按钮必须存在,my-button看起来更像是 是指令而不是组件。

结论

我建议选择最适合要求的解决方案,而不是CSS hack。

答案 8 :(得分:0)

如果您想保留旧版click事件而不使用输出。 有一个基于先前解决方案的组合解决方案。

my-button.component.html

<button [disabled]="disabled">
  <ng-content></ng-content>
</button>

我的button.component.ts

export class MyButtonComponent {
  @HostBinding('style.pointer-events') get pEvents(): string {
    if (this.disabled) {
      return 'none';
    }
    return 'auto';
  }

  @Input()
  disabled: boolean = false;

 constructor() {}
}

父组件,您将在其中调用组件,例如 app.component.html

<my-button [disabled]="isDisabled" (click)="onClickFnc()">
  <span>Save which not trigger click when button is disabled</span>
</my-button>