Angular 2 FormBuilder disable fields on checkbox select

At first, I believe that you want to enable fields if and only if isResetPassword checkbox is selected, right? If so, here we go:

1 - The construction of the form should be like this:

this.userProfileForm = this.formBuilder.group({
  // ...
  password: [{
    value: null,
    disabled: !this.isResetPassword
  }],
  newPassword: [{
    value: null,
    disabled: !this.isResetPassword
  }],
  reTypePassword: [{
    value: null,
    disabled: !this.isResetPassword
  }]
});

Note that here I'm disabling inputs only when this.isResetPassword is false.

2 - To detect changes on your <input type="checkbox">, you can use either (change) in template:

<label>
  <input 
    type="checkbox" 
    [formControl]="userProfileForm.controls['isResetPassword']" 
    (change)="handleChange($event)">
  {{ 'USER_PROFILE_MODEL.RESET_PASSWORD' | translate }}
</label>

... or even, in component, using valueChanges:

this.userProfileForm.get('isResetPassword').valueChanges.subscribe(value => this.handleChange(value));

And, of course, here's the function to manipulate the state of fields.

handleChange(value: boolean): void {
  const passwordCtrl = this.userProfileForm.get('password');
  const newPasswordCtrl = this.userProfileForm.get('newPassword');
  const reTypePasswordCtrl = this.userProfileForm.get('reTypePassword');

  if (value) {
    passwordCtrl.enable();
    newPasswordCtrl.enable();
    reTypePasswordCtrl.enable();
  } else {
    passwordCtrl.disable();
    newPasswordCtrl.disable();
    reTypePasswordCtrl.disable();
  }
}

Some tips:

1 - Although it's only a matter of preference, it's worth to mention that you don't need to use [formControl] like this:

[formControl]="userProfileForm.controls['isResetPassword']"

Instead, you can simply use formControlName:

formControlName="isResetPassword"

Note that you can do the same for all your controls.

2 - You don't need to pass the form value in (ngSubmit) since you've already the reference of userProfileForm in form.

Instead of:

(ngSubmit)="submitForm(userProfileForm.value)"

submitForm(value: any) { console.log(value); }

This:

(ngSubmit)="submitForm()"

submitForm() { console.log(this.userProfileForm.value); }

3 - If you want to see the value of disabled inputs, instead of .value, you should use .getRawValue(), like this:

this.userProfileForm.getRawValue();

DEMO (using (change))

DEMO (using valueChanges)


The easiest way would be to create a form group just for the passwords:

this.userProfileForm = formBuilder.group({
  'userName': [null, [Validators.required]],
  'displayName': [null],
  'email': [null, [Validators.required]],
  password: formBuilder.group({
    'isResetPassword': this.isResetPassword,
    'password': [null],
    'newPassword': [null],
    'reTypePassword': [null]
  })
})

Then on your template change the passwords col to this:

<div class="col" formGroupName="password>
  <div class="form-group ">
    <label class="checkbox-inline">
      <input type="checkbox" formControlName="isResetPassword">  
      {{ 'USER_PROFILE_MODEL.RESET_PASSWORD' | translate }}
    </label>
  </div>
  <div class="form-group ">
    <label>{{ 'USER_PROFILE_MODEL.PASSWORD' | translate }}</label>
    <input class="form-control" type="password" formControlName="password" >
  </div>
  <div class="form-group ">
    <label>{{ 'USER_PROFILE_MODEL.NEW_PASSWORD' | translate }}</label>
    <input class="form-control" type="password" formControlName="newPassword">
  </div>
  <div class="form-group ">
    <label>{{ 'USER_PROFILE_MODEL.RE_TYPE_PASSWORD' | translate }}</label>
    <input class="form-control" type="password" formControlName="reTypePassword">
  </div>
</div>

on your component:

//when value changes, to disable all the fields just do this
this.userProfileForm.controls.password.disable();
// to enable them back
this.userProfileForm.controls.password.enable();

Most of the methods on this post works but you need to do it with a setTimeout:

setTimeout(() => {
    if (this.disable) {
       this.userProfileForm.controls.password.disable();
    }
    else {
        this.userProfileForm.controls.password.enable();
    }
});

Looks like an Angular bug, issues here and here