简体   繁体   中英

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.

@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...

...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.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. 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. See 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. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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