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.
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) })
}