反应形式-禁用属性


97

我正在尝试使用中的disabled属性formControl。当我将其放在模板中时,它可以工作:

<md-input formControlName="id" placeholder="ID" [disabled]="true"></md-input>

但是浏览器提醒我:

看起来您正在使用带有反应形式指令的Disabled属性。如果在组件类中设置此控件时将Disabled设置为true,则实际上将在DOM中为您设置disabled属性。我们建议使用这种方法来避免“检查后更改”错误。

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

因此,我将其放在中FormControl,并从模板中删除:

constructor(private itemsService: ItemsService) {
    this._items = [];
    this.myForm = new FormGroup({
        id: new FormControl({value: '', disabled: true}, Validators.required),
        title: new FormControl(),
        description: new FormControl()
    });
    this.id = this.myForm.controls['id'];
    this.title = this.myForm.controls['title'];
    this.description = this.myForm.controls['description'];
    this.id.patchValue(this._items.length);
}

但是它不起作用(它没有禁用input)。问题是什么?


1
这似乎与角2的当前版本就好了工作:plnkr.co/edit/CQQtkYC9D5EoH0sAlNCV?p=preview
silentsod

我正在使用最新的cli项目进行测试
FacundoGFlores

2
您正在使用@ angular / material,因此,根据其github问题:github.com/angular/material2/issues/1171 尚不支持,它们处于alpha状态,因此您不能指望它具有完整的功能。
–silentsod

是的,这就是问题所在
FacundoGFlores

6
您可以尝试将其this.myForm.controls['id'].disable()放在构造函数中。我做了一个库,可以更轻松地处理动态表单:github.com/mat3e/dorf
mat3e

Answers:


116

我一直在使用,[attr.disabled]因为我仍然喜欢此模板而不是编程的enable()/ disable(),因为它是高级IMO。

更改

<md-input formControlName="id" placeholder="ID" [disabled]="true"></md-input>

<md-input formControlName="id" placeholder="ID" [attr.disabled]="true"></md-input>

如果您使用的是新材料,请更改md-inputmat-input


1
有效,谢谢!但是我不明白为什么我应该使用“ attr.disabled”(不仅是“ disabled”)?
谢尔盖·安德烈耶夫

6
请注意,使用[attr.disabled]不能以两种方式使用绑定它。它只能工作一次。使用[disabled]和控制台中的警告正在起作用。我正在使用Angular 4.1.3
The.Bear,

2
我认为这[attr.disabled]不会触发[disabled]显示的警告
K1ngjulien_

3
您能详细说明为什么您认为它“优越”吗?
拉扎尔(LazarLjubenović),

1
表单字段的属性可从HTML模板读取。假设有一个美好的一天,您决定看看是什么使给定字段无效,本能是从HTML模板向打字稿代码过渡,而不是其他方式。
bhantol '18 -10-1

13

您可以使用以下方法启用/禁用表单控件:

control.disable()或control.enable()

如果那不起作用,您可以使用指令

import { NgControl } from '@angular/forms';

@Directive({
  selector: '[disableControl]'
})
export class DisableControlDirective {

  @Input() set disableControl( condition : boolean ) {
    const action = condition ? 'disable' : 'enable';
    this.ngControl.control[action]();
  }

  constructor( private ngControl : NgControl ) {
  }

}

那你可以这样用

<input [formControl]="formControl" [disableControl]="disable">
<button (click)="disable = true">Disable</button>
<button (click)="disable = false">Enable</button>

此处介绍了此技术:

https://netbasal.com/disabling-form-controls-when-working-with-reactive-forms-in-angular-549dd7b42110

希望能帮助到你


您能
请教

请提供任何样本
kumaresan_sd '19


这不适用于NgControl (`No provider for NgControl`)
Angular8

1
我可以确认从Angular 8起该解决方案不再起作用!
Martijn Hiemstra


9

就我的角度8。我想根据情况切换输入的启用/禁用。

[attr.disabled] 不适用于我,所以这是我的解决方案。

[attr.disabled]从HTML中删除,并在组件函数中执行了此检查:

if (condition) {
    this.form.controls.myField.disable();
} else {
    this.form.controls.myField.enable();
}

4

初始化(组件)使用:

public selector = new FormControl({value: '', disabled: true});

然后,而不是使用(模板):

<ngx-select
[multiple]="true"
[disabled]="errorSelector"
[(ngModel)]="ngxval_selector"
[items]="items"
</ngx-select>

只需删除禁用的属性即可:

<ngx-select
[multiple]="true"
[(ngModel)]="ngxval_selector"
[items]="items"
</ngx-select>

当您有要显示的项目时,启动(在组件中): this.selector.enable();


2

仅谁使用反应形式: 对于本机HTML元素[attr.disabled]将起作用,但对于实体元素,我们需要动态禁用该元素。

this.form.get('controlname').disable();

否则它将显示在控制台警告消息中。


2

我在角度7中进行了尝试。

this.form.controls['fromField'].reset();
if(condition){
      this.form.controls['fromField'].enable();
}
else{
      this.form.controls['fromField'].disable();
}

2
this.form.disable()
this.form.enable()

对于一个formcontrol使禁用

this.form.get('first').disable()
this.form.get('first').enable()

或初始设置方法。

first: new FormControl({disabled: true}, Validators.required)

1

使用[attr.disabled]代替[disabled],就我而言,它可以正常工作


2
尽管这可能是可行的,但在使用反应式表单时,不应使用模板驱动的解决方案。混合这两者的问题是,反应形式状态不再受信任。
enf0rcer

它用于禁用,但如果我将其设置为false,也可以控制禁用
-kumaresan_sd

1

将disable =“ true”添加到html字段示例:disable

<amexio-text-input formControlName="LastName" disable="true" [(ngModel)]="emplpoyeeRegistration.lastName" [field-label]="'Last Name'" [place-holder]="'Please enter last name'" [allow-blank]="true" [error-msg]="'errorMsg'" [enable-popover]="true" [min-length]="2"
[min-error-msg]="'Minimum 2 char allowed'" [max-error-msg]="'Maximum 20 char allowed'" name="xyz" [max-length]="20">
[icon-feedback]="true">
</amexio-text-input>


此答案无法以回避形式起作用。这与模板驱动形式有关
Nambi N Rajan

1

响应式表单的优点在于,您可以轻松地捕获任何输入元素的值更改事件,同时可以更改其值/状态。因此,这是使用来解决您的问题的另一种方法enable disable

这是关于stackblitz的完整解决方案。


我建议您也将代码张贴在这里,或者至少是一段代码。我发现此解决方案很有用,因此订阅值更改并触发启用/禁用似乎是一个不错的选择。
约翰·怀特

1

如果您使用表单验证,则可免除禁用mat表单字段,因此请确保您的表单字段没有任何验证(例如validator.required),这对我有用。例如:

editUserPhone:新的FormControl({value:'',disabled:true})

这使用户的电话号码不可编辑。


1

这是我的解决方案:

this.myForm = this._formBuilder.group({
    socDate: [[{ value: '', disabled: true }], Validators.required],
    ...
)}

<input fxFlex [matDatepicker]="picker" placeholder="Select Date" formControlName="socDate" [attr.disabled]="true" />

1
嗨,弗兰克,欢迎您使用StackOverflow,并感谢您的答复!虽然在代码中提供有效的解决方案固然很棒,但是如果您在代码之外添加了一些说明,则可以帮助其他人现在和将来更好地理解您的答案。
robsiemb

1

Angular-9中,如果要禁用/启用按钮单击,则在使用反应式表单时,这是一种简单的解决方案。

在component.ts文件中定义一个函数

//enable example you can use the same approach for disable with .disable()

toggleEnable() {
  this.yourFormName.controls.formFieldName.enable();
  console.log("Clicked")
} 

从您的component.html中调用它

例如

<button type="button" data-toggle="form-control" class="bg-primary text-white btn- 
                reset" style="width:100%"(click)="toggleEnable()">



-4

做到这一点的最终方法。

ngOnInit() {
  this.interPretationForm.controls.InterpretationType.valueChanges.takeWhile(()=> this.alive).subscribe(val =>{
    console.log(val); // You check code. it will be executed every time value change.
  })
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.