Search code examples
angularangular6angular-reactive-formsangular-formsangular4-forms

Angular reactive forms custom validator. Enable Validation only when checkbox checked


I have a problem validating the checkbox that are marked only. At first, when the component is initialize and all checkbox are disabled, if they click the save button it should output a validation that says you didn't click any checkbox. Second validation is when you have mark a checkbox but you didn't enter any quantity, it should only mark that "This field is required". Now however, when i click the save button, all quantity even though is disabled, the error "This field is required" is appearing. How can i solve this? Please also my commented functions, maybe this will help. Thanks.

Please click here for my stackblitz link : CODE LINK

patchValues() {
    let rows = this.myForm.get('rows') as FormArray;
    this.orders.forEach(material => {
      material.materials.forEach(x => {
        rows.push(this.fb.group({
          checkbox_value: [null],
          material_id: new FormControl({ value: x.id, disabled: true }, Validators.required),
          material_name: x.name,
          quantity: [null]
        }));
        // this.formArrayLength++;
      });
    });
  }

Solution

  • You need to create custom validators for you form and subforms in array.

    For form its valid when one of checkboxes checked. And looks like

    formValidator(control: AbstractControl): { [key: string]: any } {
       return control.value.rows.some(i => i.checkbox_value) ? null : { 'checkboxReq': 'Some checkbox field is required' }
    }
    

    Add it to you form

    this.myForm.setValidators([this.formValidator.bind(this)])
    

    In template you can get it with myForm.getError('checkboxReq')

    <small class="form-text text-muted danger">{{myForm.getError('checkboxReq')}}</small>
    

    For subform need another validator

    subFormValidator(control: AbstractControl): { [key: string]: any } {
       return control.value.checkbox_value ? { 'req': 'This field is required' } : null
    }
    

    Add it when you init you subForm

    (this.fb.group({
          checkbox_value: [null],
          material_id: [{ value: x.id, disabled: true }],
          material_name: x.name,
          quantity: [null]
        }, [this.subFormValidator.bind(this)]));
    

    Template

    <small class="form-text text-muted danger" *ngIf="row.invalid && row.touched">This field is required</small>
    

    stackblitz example with changes