Search code examples
angularangular2-forms

Angular 2 FormGroup valid when not all his FormControls are valid


As I already wrote in the title, is that possible to have a form group that has multiple FormControls and the group be valid when not all of its Controls are valid?

private moreInfoForm : FormGroup = this.formBuilder.group({
    location: this.formBuilder.group({
        predefined: [''],
        custom: ['']
    }),
    demand_room: ['', [Validators.required]],
    motivation: ['', Validators.required],
    expectaions: ['', [Validators.required]],
    participation: this.formBuilder.group({
        all: [''],
        wednesday: [''],
        thursday: [''],
        friday: [''],
        saturday: ['']
    }),
    donations: ['', Validators.required],
    comments: ['', Validators.required]
});

https://plnkr.co/edit/v1v6UTrLypFqLpI1KNo7

For the location group I have a predefined and custom fields. For predefined there is a and for custom there is an input field. Is that possible to validate the group when the user chose either 'predefined' either 'custom'.

The other one is on the participation. Those are checkboxes and the form should be valid when the user checked one of those chekcboxes.

Thanks.


Solution

  • You can use a custom validator, to check that either predefined or custom has a value, here let's call it validateGroup:

    location: this.formBuilder.group({
      predefined : [''],
      custom : ['']
    },{
        validator: (formGroup: FormGroup) => {
          return this.validateGroup(formGroup);
        }
    }),
    

    And the corresponding function checking that either is filled, where we return null if it is valid:

    private validateGroup(formGroup: FormGroup) {
      for (let key in formGroup.controls) {
        if (formGroup.controls.hasOwnProperty(key)) {
          let control: FormControl = <FormControl>formGroup.controls[key];
          if (control.value) {
            return null;
          }
        }
      }
      return {
        validateGroup: {
          valid: false
        }
      };
    }
    

    This same function, validateGroup you can use with your days, so your final build of form would look like this:

      private moreInfoForm : FormGroup = this.formBuilder.group({
        location: this.formBuilder.group({
          predefined : [''],
          custom : ['']
        },{
            validator: (formGroup: FormGroup) => {
              return this.validateGroup(formGroup);
            }
        }),
        demand_room : ['', [Validators.required]],
        motivation : ['', Validators.required],
        expectaions : ['', [Validators.required]],
        participation : this.formBuilder.group({
          all : [''],
          wednesday : [''],
          thursday : [''],
          friday : [''],
          saturday : ['']
        },{
            validator: (formGroup: FormGroup) => {
              return this.validateGroup(formGroup);
            }
        }),
        donations : ['', Validators.required],
        comments : ['', Validators.required]
      });
    

    You can read more about the above, on this page.

    Here's your forked

    Plunker

    PS. Please notice the changes I also did to the radio buttons, so that it will be properly added to your form:

    demand_rooms = ['Yes','No'];
    
    <label *ngFor="let demand_room of demand_rooms">
      <input type="radio" name="demand_room" formControlName="demand_room" [value]="demand_room">Yes
    </label>