6
votes

I'm dynamically creating reactive forms in Angular based on JSON data received from API. Sometimes form has only several formControls but sometimes there are a lot of form groups or formArrays with FormGroups.

I have a question about FormArray with several FormGroups. In this FormGroups some FormControls can be required and some not. But the whole FormGroup is not required. Only if some FormControls in group are edited, after that whole form group must be valid (every required FormControl can't be empty).

So my question is how to create custom validator for whole FormGroup, which will secure that if every FormControl in these concrete group will be empty, then this group will be valid. But if for example one FormControl will be edited, then every required FormControl must be filled.

Thanks a lot for your ideas.

2
Please add your code.Ashley
Code for my solution is very extensive and I can't share it from security reasons. My question is only about custom generic validator which will work like I wrote in my question. Sorry.irudji
FYI, in the future, if you can't add your exact code for whatever reason, you should create a simplified version that demonstrates your problem.bryan60

2 Answers

5
votes

What about trying this simple solution

this is my form init

this.sponsorshipForm = this.fb.group(
  {
    startDate: ['', [Validators.required]],
    endDate: ['', [Validators.required]]
  },
  { validators: [this.sponsorshipDurationValidation] }
);

and this is my validator you can make whatever you need and customize it

sponsorshipDurationValidation(form: FormGroup) {
   if (form.value.startDate && form.value.end) {
     console.log('form ', form, form.status);
   }
   if (something false happen or not valid value) {
     return { validUrl: true };
  }
  return null;
}
3
votes

you add form group level validators like this using FormBuilder service:

this.myFormGroup = this.formBuilder.group({ 
                     ... my group info ... 
                   }, {validators: [... validators ... ]);

the custom validator acts like any other, but the abstract control in this case is a FormGroup that can be treated like any other form group.

something like:

function allOrNoneRequired(): ValidatorFn {
  return (ctrl: AbstractControl): ValidationErrors | null => {
    const fg = ctrl as FormGroup;
    const controls = Object.values(fg.controls);
    return (controls.every(fc => !fc.value) || controls.every(fc => !!fc.value))  
             ? null 
             : {allOrNoneRequired: true};
  };
}

then

this.myFormGroup = this.formBuilder.group({ 
                     ... my group info ... 
                   }, {validators: [allOrNoneRequired()]);