简体   繁体   English

角度形式禁用对valueChanges的控制

[英]Angular form disable control on valueChanges

I am trying to disable a form control when one of my form group value changes but the problem is that the method disable() and enable() also updates the form status, so I have an infinite loop. 我试图在我的一个表单组值更改时禁用表单控件,但问题是方法disable()enable()也更新表单状态,所以我有一个无限循环。

@Component({
  selector: 'my-app',
  template: `
   <form [formGroup]="questionForm">

     <input type="text" formControlName="question" />

     <input type="text" formControlName="other"/>
   </form>
  `,
})
export class App {

  constructor(private fb: FormBuilder) {  
     this.questionForm = this.fb.group({
       question: [''],
       other: ['']
     });
  }

  ngOnInit() {
     this.questionForm.valueChanges.subscribe(v => {
       if(v.question === 'test') {
         this.questionForm.get('other').disable();
       } else {
          ...enable()
       }
     })
  }

}

How can I solve this problem? 我怎么解决这个问题?

Well, according to the official docs you could use an directive for custom validation, this could of course in your case could be applied with logic of checking what the user has input and then disable and enable the other field. 好吧,根据官方文档,您可以使用指令进行自定义验证,当然,在您的情况下,可以应用逻辑来检查用户输入的内容,然后禁用并启用其他字段。 There's quite a lot of code there, sooooo... 那里有很多代码,sooooo ......

...You could also do a smaller hack if you do not want all that bunch of code. ...如果你不想要那么多代码,你也可以做一个小的黑客攻击。 Let's call a function that checks what user has typed. 让我们调用一个函数来检查用户键入的内容。 We also need to bind this , so we can refer to the questionForm : 我们还需要绑定this ,所以我们可以参考questionForm

 this.questionForm = this.fb.group({
   question: ['', [this.checkString.bind(this)]],
   other: ['']
 });

Then the function: 然后功能:

checkString(control: FormControl) {
  if(control.value == 'test') {
    this.questionForm.get('other').disable()
  }
  // we need to check that questionForm is not undefined (it will be on first check when component is initialized)
  else if (this.questionForm) { 
    this.questionForm.get('other').enable()
  }
}

This seems to serve it's purpose. 这似乎符合它的目的。

Demo 演示

Hope this helps! 希望这可以帮助! :) :)

With reactive forms, you do it something like this: 使用反应形式,你可以这样做:

question: {value: '', disabled: true }

在此输入图像描述

I would first add a property isDisabled to your component, then I would use the [disabled] directive. 我首先将一个属性isDisabled添加到您的组件,然后我将使用[disabled]指令。 This would solve your looping issue. 这将解决您的循环问题。

@Component({
    selector: 'my-app',
    template: `
<form [formGroup]="questionForm">

    <input type="text" formControlName="question" />

    <input type="text" formControlName="other" [disabled]="isDisabled" />
</form>
`,
})
export class App {

    isDisabled = false;

    constructor(private fb: FormBuilder) {
        this.questionForm = this.fb.group({
            question: [''],
            other: ['']
        });
    }

    ngOnInit() {
        this.questionForm.valueChanges.subscribe(v => {
            if (v.question === 'test') {
                this.isDisabled = true;
            } else {
                this.isDisabled = false;
            }
        })
    }

}

Adding another answer to work around the reactive forms issue using two controls and an *ngIf directive. 使用两个控件和一个* ngIf指令添加另一个解决反应形式问题的答案。 See https://github.com/angular/angular/issues/11324 . 请参阅https://github.com/angular/angular/issues/11324

This solution may not be ideal as it requires that you add a second form control that will appear when the conditions for changing the isDisabled property are met. 此解决方案可能并不理想,因为它要求您添加第二个表单控件,该控件将在满足更改isDisabled属性的条件时显示。 This means there are two controls to manage when submitting the form. 这意味着在提交表单时需要管理两个控件。

@Component({
    selector: 'my-app',
    template: `
<form [formGroup]="questionForm">

    <input type="text" formControlName="question" />

    <input *ngIf="isDisabled" type="text" formControlName="other" disabled />
    <input *ngIf="!isDisabled" type="text" formControlName="other2"  />
</form>
    `
    providers: [FormBuilder]
})
export class App {

    isDisabled = true;

    constructor(private fb: FormBuilder) {
        this.questionForm = this.fb.group({
            question: [''],
            other: [''],
            other2: ['']
        });
    }

    ngOnInit() {
        this.questionForm.valueChanges.subscribe(v => {
            if(v.question === 'test') { 
                this.isDisabled = false;
            } else {
                this.isDisabled = true;
            }
        });
    }

}

Check out or play with the plunker if you wish: 如果您愿意,可以检查或玩弄羽毛球:

https://plnkr.co/edit/0NMDBCifFjI2SDX9rwcA https://plnkr.co/edit/0NMDBCifFjI2SDX9rwcA

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM