7

I'm using angular 7 and I have a form with two input fields, while the first one is always required, the second one should be required only if a checkbox is checked.

I'm trying to use a FormGroup with a custom validator:

<form [formGroup]="exampleForm">
  <mat-form-field>
    <input matInput placeholder="first" formControlName="first">
  </mat-form-field>
  <mat-checkbox [(ngModel)]=" checked" [ngModelOptions]="{standalone:true}">Make second input field required</mat-checkbox>
  <mat-form-field>
    <input matInput placeholder="second" formControlName="second">
  </mat-form-field>
</form>

exampleForm: FormGroup;
checked: boolean;

ngOnInit() {
  this.exampleForm = new FormGroup({
    'second': new FormControl('', [this.validateIfChecked()]),
    'first': new FormControl('example', [Validators.required])
  });
}


validateIfChecked(): ValidatorFn {
  return (control: AbstractControl): {
    [key: string]: any
  } | null => {
    if (this.checked) {
      return control.value ? null : {
        'err': true
      };
    }
    return null;
  }
}

The problem is that the validation is performed only when the text in the two input fields is updated, while if I check/uncheck the checkbox the state doesn't change and to force the validation I have to change the text in the second textbox.

Here you can see an example on stackblitz: if you check the checkbox, the status doesn't change.

How can can I force the validation when the checkbox status changes?

1
  • what about disabled the input? NOTE: you must disable and enable the control using exampleForm.controls.second.disable() and exampleForm.controls.second.enable(). stackblitz.com/edit/angular-d7hj6a?file=src/app/… Commented Feb 21, 2019 at 17:27

3 Answers 3

5

You need to use crossfield validation. Include the checkbox in your formgroup

<form [formGroup]="exampleForm">
    <mat-form-field>
    <input matInput placeholder="first" formControlName="first">
    </mat-form-field>
    <mat-checkbox formControlName="checked">Make second input field required</mat-checkbox>
    <mat-form-field>
    <input matInput placeholder="second" formControlName="second">
    </mat-form-field>
</form>
ngOnInit() {
    this.exampleForm = new FormGroup({
    'second': new FormControl(''),
    'checked': new FormControl(false),
    'first': new FormControl('example')
    }, [this.validateIfChecked()]);
}


validateIfChecked(): ValidatorFn {
    return (form: FormGroup): ValidationErrors | null => {
    const checked = form.get('checked');
    const second= form.get('second');
    if (checked && !second) {
        return {
        'err': true
        };
    }
    return null;
    }
}

In this case, if 'checked' is true then 'second' is required

if in doubt https://angular.io/guide/form-validation#cross-field-validation

Sign up to request clarification or add additional context in comments.

Comments

4

If you actually don't want to include the checkbox value to your form, you can make a separate form control, which is not included in your form. Based on the checkbox value you can clear validators or add required validator:

checked = new FormControl(false);

// ...

this.checked.valueChanges.subscribe((bool: boolean) => {
  bool ? this.exampleForm.get('second').setValidators(Validators.required) : 
         this.exampleForm.get('second').clearValidators();
  this.exampleForm.get('second').updateValueAndValidity();
});

And the relevant template:

<mat-checkbox [formControl]="checked">Make second input field required</mat-checkbox>

Your forked StackBlitz

Comments

2

You can dynamically add validation required to the form control based on checkbox clicked.

Template:

<form [formGroup]="exampleForm">
  <mat-form-field>
    <input matInput placeholder="first" formControlName="first">
  </mat-form-field>
  <mat-checkbox [(ngModel)]="checked" [ngModelOptions]="{standalone:true}" (click)="checkstate()">Make second input field required</mat-checkbox>
  <mat-form-field>
    <input matInput placeholder="second" formControlName="second">
  </mat-form-field>
</form>

Component:

checkstate(){
  this.checked = !this.checked;
  if(this.checked){
     this.exampleForm.get('second').setValidators(Validators.required);
  }else{
     this.exampleForm.get('second').clearValidators();
  }
  this.exampleForm.get('second').updateValueAndValidity();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.