为什么 [disabled]="canDisable" 不适用于 Angular2 反应形式

Why does [disabled]="canDisable" will not work for Angular2 reactive forms

我正在尝试根据组件中的变量 "canDisable" 将 angualr2 中的反应式输入表单控件禁用为已禁用。 我的代码看起来像这样。

<input type="text" formControlName="CustomerName" Name="CustomerName" 
[disabled]="canDisable"/>

不幸的是,它没有按预期工作,谁能告诉我原因。

但是,它工作正常如果我这样做 [attr.disabled]="canDisable".

   <input type="text" formControlName="CustomerName" Name="CustomerName" 
    [attr.disabled]="canDisable"/>

经过简短的调查,我发现 disabledFormControl causes ReactiveErrors.disabledAttrWarning() 中输入的设置:

It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
you. We recommend using this approach to avoid 'changed after checked' errors.

  Example: 
  form = new FormGroup({
    first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
    last: new FormControl('Drew', Validators.required)

根据 this comment 看来,另一种官方解决方案似乎是手动调用 FormControl.disable() 方法,上述原因再次与变更检测有关。我同意它可以被认为是一个错误...... 在 angular/material2 存储库中也有一些解释:https://github.com/angular/material2/issues/2667#issuecomment-275280698

如您所见in the docs禁用的控件免于验证检查,并且不包含在其祖先控件的聚合值中。 - 也许这是另一个有理由明确地这样做。

[disabled]property binding。 angular 团队似乎不再允许在 Reactive Forms 中使用它。要禁用它,您需要使用 FormControl

中的 disable() 方法

另一方面,在我看来,当您通过 attribute binding => [attr.disabled] 进行绑定时,他们并没有应用相同的行为(我不知道这是一个错误还是他们是故意这样做的,因为大多数人使用 property binding 多于 attribute binding

所以我想说你正在寻找的原因是:angular 团队已阻止使用 disabled 属性 绑定 但不是 禁用响应式表单上的属性绑定

你可以看到 this discussion 关于 属性 绑定的使用,并且看到一些人使用属性绑定到 "solve their problem" 但 angular 团队没有人说一件事关于它。

为什么通过属性绑定在 Reactive Forms 上使用 disabled 有效而使用 属性 绑定无效的原因是您需要询问 Angular 团队。你可以打开一个关于它的问题。

import { AfterViewInit, ChangeDetectorRef, Directive, ElementRef, Input, Renderer2 } from "@angular/core";

@Directive({
    selector: "[customDisable]"
})
export class CustomDisableDirective implements AfterViewInit {

    private _isDisabled: boolean = false;

    @Input('value')
    set isDisabled(value) {
        this._isDisabled = value;
        this.changeDetector.markForCheck();
        this.changeDetector.detectChanges();
    }

    constructor(public el: ElementRef, private renderer: Renderer2, private changeDetector: ChangeDetectorRef) { }

    ngAfterViewInit(): void {
        // Force the control to disable
        this.renderer.setProperty(this.el.nativeElement, 'disabled', this._isDisabled);
    }

}