Angular Material 12中@HostBinding('disabled')作用于mat按钮失效问题
Angular Material v12中自定义指令通过@HostBinding绑定disabled属性失效问题
我编写了一个自定义指令,内置特定逻辑用于控制按钮禁用状态,指令代码如下:
@Directive({ selector: '[myDirective]', }) export class MyDirective { @HostBinding('disabled') disabled = true; constructor() { } @Input('myDirective') set myData(data: string[]) { this.disabled = someDirectiveLogic(data); } // ... }
该指令在普通HTML按钮上使用时功能正常,调用示例如下:
<a mat-raised-button color="accent" [disabled]="system.selection.length === 0" >View</a> <button color="accent" [myDirective]="system.selection" >Pause</button>
此时功能表现符合预期:
- 无选中数据时,右侧Pause按钮禁用:

- 选中数据后,右侧Pause按钮启用:

当我给Pause按钮添加mat-raised-button属性后,在Angular Material v12版本下该按钮始终显示为启用状态,预期应为无选中数据时禁用:
相同的代码在Angular Material v6.3版本中运行正常,指令设置的disabled属性可与mat-raised-button配合正常渲染。
请问是否无法在Angular Material 12中使用@HostBinding('disabled')绑定material按钮的禁用状态?应如何解决该问题?
问题原因
Angular Material 从v8之后的版本逐步调整了按钮组件的状态管理逻辑,到v12版本时,mat-button系列组件的disabled状态优先读取组件自身的@Input() disabled值,原生DOM的disabled属性优先级低于组件内部输入属性,因此你通过@HostBinding绑定原生属性的操作会被Material组件的内部默认值覆盖,导致失效。而v6.3版本中Material按钮还未做这层优先级处理,会直接同步原生属性的状态,所以可以正常生效。
解决方案
你可以在自定义指令中直接注入MatButton实例,修改组件内部的disabled输入属性,即可兼容Material按钮的状态管理逻辑。如果需要同时兼容普通HTML按钮和Material按钮,可以结合Optional装饰器做兼容处理:
import { Directive, Input, Optional, Renderer2, ElementRef } from '@angular/core'; import { MatButton } from '@angular/material/button'; @Directive({ selector: '[myDirective]', }) export class MyDirective { disabled = true; constructor( // 可选注入MatButton,普通按钮没有这个实例就返回null @Optional() private matButton: MatButton, private renderer: Renderer2, private elementRef: ElementRef<HTMLButtonElement> ) { } @Input('myDirective') set myData(data: string[]) { this.disabled = someDirectiveLogic(data); if (this.matButton) { // Material按钮直接修改组件输入属性 this.matButton.disabled = this.disabled; } else { // 普通按钮直接修改原生DOM属性 this.renderer.setProperty(this.elementRef.nativeElement, 'disabled', this.disabled); } } // ... }
修改后不需要调整业务侧的调用代码,普通按钮和Material按钮都可以正常触发禁用逻辑。
内容的提问来源于stack exchange,提问作者adelinor
相关产品推荐
相关产品推荐

