如何使用自定义指令使材料 <input matInput> 变为只读?
Posted
技术标签:
【中文标题】如何使用自定义指令使材料 <input matInput> 变为只读?【英文标题】:How to make material <input matInput> become readonly with custom directive? 【发布时间】:2021-01-05 02:24:02 【问题描述】:我想使用我的自定义指令使使用材料matInput
的<input>
变为只读。指令isControlReadonly
将用于根据安全标准设置只读。问题是它适用于<input>
,但对<input matInput>
没有影响
所以.. 第一个输入有效,第二个无效:
<!-- this works -->
<input type="input" formControlName="test_field" isControlReadonly>
<!-- this doesn't works -->
<mat-form-field appearance="standard">
<mat-label>Name</mat-label>
<input matInput type="input" formControlName="customer_name" isControlReadonly>
</mat-form-field>
这是指令:
import Directive, ElementRef, OnInit, ViewChildren from '@angular/core';
import SecurityService from './security.service';
@Directive(selector: '[isControlReadonly]')
export class IsReadonlyDirective implements OnInit
constructor(
private elementRef: ElementRef,
private securityService: SecurityService
)
ngOnInit(): void
var ro = !this.securityService.user.canEdit
this.elementRef.nativeElement.setAttribute('readonly', ro)
请帮助如何使该自定义指令与 matInput 一起使用?
编辑注意:我不想从反应形式设置只读,因为指令是更干净的代码。我不想在我的组件中添加逻辑,我想要指令中的逻辑,因为它是集中式的,将用于所有表单。
谢谢
【问题讨论】:
您在响应式表单中使用只读属性,请查看此anwser ***.com/a/54920060/6823766 我不想从响应式表单中设置只读,因为指令是更简洁的代码。我不想在我的组件中添加逻辑,我想要指令中的逻辑,因为它是集中式的,将用于所有表单。 通过使用响应式表单,您已经将逻辑移动到组件中。这就是响应式表单的全部意义——在打字稿代码中包含逻辑,而不是在整个模板中传播它。如果您想保留模板上的逻辑,那么模板驱动的表单是可行的方法。 请仔细阅读案例。问题是“为什么它不适用于 matInput”?在我的方法中,没有像你说的那样“遍布整个模板的代码”。这就是我使用指令的原因,所以逻辑将在指令中。你能想象我必须对我所有的反应形式进行安全检查吗?相反,我可以将逻辑放在指令中的单个位置。所以它比你建议的要干净得多 【参考方案1】:编辑:之前提供了禁用解决方案。 要使输入只读移动您的逻辑到“ngAfterViewInit” 这是您的指令的一个工作示例:
@Directive(selector: '[isControlReadonly]')
export class IsReadonlyDirective implements OnInit, AfterViewInit
constructor(
private elementRef: ElementRef,
private control: NgControl,
private securityService: SecurityService
)
ngAfterViewInit(): void
var ro = !this.securityService.user.canEdit
this.elementRef.nativeElement.setAttribute('readonly', ro)
【讨论】:
感谢它适用于disable()
,但我需要readonly
,因为它获得焦点并且没有变灰
我的错!将您的逻辑移动到“ngAfterViewInit”并实现“AfterViewInit”。然后一切都应该正常工作。 ngAfterViewInit(): void var ro = !this.securityService.user.canEdit this.elementRef.nativeElement.setAttribute('readonly', ro)
这就是我要找的。有用!非常感谢【参考方案2】:
您的指令适用于所有类型的输入,但在 mat-input 的情况下,由您的指令设置的 readonly 属性被 Angular Material 自己的readonly
@Input 覆盖。
在此处参考 Mat-Input 的源代码:Mat-Input Readonly @Input 了解更多信息
因此,您可以做的是让设置属性的代码执行出堆栈并将其交给事件循环。这样,您的代码将在 Angular 操作之后执行。最常见的实现方式是setTimeout
,延迟为 0 秒
setTimeout(() =>
this.elementRef.nativeElement.setAttribute('readonly', ro)
);
这是一个有效的BLITZ
【讨论】:
以上是关于如何使用自定义指令使材料 <input matInput> 变为只读?的主要内容,如果未能解决你的问题,请参考以下文章