Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 FormBuilder Validators: require at least one field in a group to be filled

I have a form where I'm collecting phone numbers (mobile, personal, other). I need to have at least input populated. I'm trying to use Angular2 FormBuilder.

After much research I'm having a problem getting my head around this problem. I know I can do it using other methods but I was wondering if it's possible using FormBuilder Validators. If I add "Validators.required" then all 3 fields are required. Any suggestions or ideas?

phone: this._fb.group(                     {                         other: [''],                         personal: [''],                         mobile: [''],                     } 

Base on the hint from " JB Nizet", here's what I had to implement to make it work:

My group Validator (it still needs tweaking):

static phoneExists(group: FormGroup): { [key: string]: any } {      if (null != group) {         var other: AbstractControl = group.controls['other'];         var mobile: AbstractControl = group.controls['mobile'];         var personal: AbstractControl = group.controls['personal'];         var data: Object = group.value;          return (             (other.valid && isEmptyInputValue(other.value))             && (mobile.valid && isEmptyInputValue(mobile.value))             && (personal.valid && isEmptyInputValue(personal.value))             )             ? { 'required': true }             : null;     } } 

My group change:

phone: this._fb.group(                     {                         other: [''],                         personal: [''],                         mobile: [''],                     },                     { validator: MyValidators.phoneExists }                 ) 

It took me a while, but the key is to add the key word "validator" and it will cause the group validator to fire.

In the HTML i added the following:

<small *ngIf="!myForm.controls.profile.controls.phone.valid" class="text-danger">                                         At least one phone is required.                                     </small> 

I hope this help anyone else.

like image 505
Manny Avatar asked Oct 29 '16 16:10

Manny


People also ask

Is it possible to define validators in FormBuilder?

FormBuilder allows us to explicitly declare forms in our components. This allows us to also explicitly list each form control's validators.

How will you add validators in FormControl?

Adding async validators to reactive formslink To use an async validator in reactive forms, begin by injecting the validator into the constructor of the component class. Then, pass the validator function directly to the FormControl to apply it.

What is difference between FormBuilder and FormControl?

The official docs describe it as: Creating form control instances manually can become repetitive when dealing with multiple forms. The FormBuilder service provides convenient methods for generating controls. So basically saying that FormBuilder is a service that is trying to help us reduce boiler-plate code.

How do I set validators for FormArray?

To create a FormArray , we can pass an array of FormControl or FormGroup . A FormArray is called validated only if its FormControl or FormGroup are validated. We can validate FormArray with synchronous and async validators. On this page we will create a reactive form using FormBuilder and validate it.


1 Answers

I use an atLeastOne function that creates a custom validator based on any existing validator:

import { FormGroup, ValidationErrors, ValidatorFn } from '@angular/forms';  export const atLeastOne = (validator: ValidatorFn) => (   group: FormGroup, ): ValidationErrors | null => {   const hasAtLeastOne =     group &&     group.controls &&     Object.keys(group.controls).some(k => !validator(group.controls[k]));    return hasAtLeastOne ? null : { atLeastOne: true }; }; 

The beauty is that you can use any validator with it and not just Validators.required.

In OP's case, it'll be used like this:

{   phone: this._fb.group({     other: [''],     personal: [''],     mobile: [''],   }, { validator: atLeastOne(Validators.required) }) } 
like image 111
Merott Avatar answered Oct 22 '22 13:10

Merott