Angular 4 - Reactive Forms enable/disable not working

Kashif Nazar picture Kashif Nazar · Apr 26, 2018 · Viewed 11.8k times · Source

I am having trouble enabling and disabling a form controls in my application. It is probably because the form is being enabled/disabled in an asynchronous context.

Here is how the code is.

user.component.html

<form [formGroup]="form">
    <input type="text" id="name" formControlName="name" />
    <input type="text" id="age" formControlName="age" />
</form>

user.component.ts

ngOnInit() {

     this._route.queryParams.subscribe(params => {
            getUser(params.userId).subscribe(user => {
                 this._buildForm(user);
            })
     });
}

private _buildForm(user){
    this.form = _fb.group({
        name: [{value: user.name, disabled: user.someCondition}, Validators.required],
        age: [{value: user.age, disabled: user.anotherCondition}, Validators.required]
    })
}    

When the first time the user is loaded upon param change, the controls do get enabled/disabled on the basis of their relevant conditions. When the params change subsequently, the state of the controls remain the same although the values are set appropriately.

I have tried different ways to fix this but no help. For example, I have tried the following at the end of the _buildForm method.

this.form.disable() //Doesn't do anything

this.form.controls.name.disable(); //Doesn't help

One thing that does work as expected is the following (but this isn't what is required).

<button (click)="form.disable()" value="Disable Form" />
<button (click)="form.enable()" value="Enable Form" />

What I feel is that the problem is due the fact the _buildForm() is being called from the asynchronous context (subscribe method).

How can I fix this problem?

UPDATE

Please note that the Observable subscription is triggered on the basis of the navigation as below.

this._router.navigate([], {
   relativeTo: this._route,
   queryParams: {userId: 10}
})

UPDATE 2 https://angular-cvf1fp.stackblitz.io

This is an easier way to understand my problem

Answer

Sharikov Vladislav picture Sharikov Vladislav · Apr 26, 2018

You just need enable/disable methods of form control.

Here is stackblitz example. It works perfectly.

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  group;
  isDisabled = true;

  constructor(fb: FormBuilder) {
    this.group = fb.group({
      stuff: fb.control({value: 'stuff', disabled: this.isDisabled})
    });
  }

  toggle() {
    this.isDisabled = !this.isDisabled;

    this.group.controls.stuff[this.isDisabled ? 'enable' : 'disable']();
  }
}