I have my form and my custom validator right here, with logic that I think should work. I have 15 fields, 3 in which the custom validator refers to ('icmp','tcpPorts','udpPorts'). Along with the other required fields I need at least ONE of those three fields filled to submit.
here is the code in my component.ts
newFWXForm = this.fb.group(
{
sspSelect: ["", Validators.required],
requester: [this.loggedInUser],
requesterContactInfo: [this.loggedInUserEmail],
fwxDescription: ["", Validators.required],
durationTypeSelect: ["Permanent", Validators.required],
durationDate: [""],
infraSelect: [""],
sourceIPs: ["", Validators.required],
DestAnyCheck: [false],
SrcAnyCheck: [false],
icmp: [false],
destinationIPs: ["", Validators.required],
tcpPorts: [],
udpPorts: [],
addDirectory: new FormControl(false),
},
{
Validators: this.atleastOnePortValue("icmp", "tcpPorts", "udpPorts"),
}
);
private atleastOnePortValue( controlNameA: string,controlNameB: string,controlNameC: string): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const formGroup = control as FormGroup;
const valueOfControlA = formGroup.get(controlNameA)?.value;
const valueOfControlB = formGroup.get(controlNameB)?.value;
const valueOfControlC = formGroup.get(controlNameC)?.value;
if (
valueOfControlA === false &&
valueOfControlB === null &&
valueOfControlC === null
) {
return { atLeastOne: true};
} else {
return null;
}
};
}
Any knowledge or help on why this still isn't working? Very much appreciated and thank you in advanced!
CodePudding user response:
NOTE: It's an answer to show how make a validator over "one control", not over the whole form
It's like this SO but extending with another field
export function conditionalValidator(field: string[]): ValidatorFn {
return (formControl) => {
if (!formControl.parent) {
return null;
}
const otherControls = field.map((x) => formControl.parent.get(x));
if (otherControls.filter((x) => x).length == field.length) {
const error =
formControl.value || otherControls.find((x) => x.value)
? null
: { error: 'this field or ' field ' is required' };
const controlCheck = error
? otherControls.filter((x) => x.valid)
: otherControls.filter((x) => x.invalid);
if (controlCheck.length) {
setTimeout(() => {
controlCheck.forEach((x) =>
x.updateValueAndValidity({ emitEvent: false })
);
});
}
return error;
}
};
}
You has, e.g.
form = new FormGroup({
control1: new FormControl(
null,
conditionalValidator(['control2', 'control3'])
),
control2: new FormControl(
null,
conditionalValidator(['control1', 'control3'])
),
control3: new FormControl(
null,
conditionalValidator(['control1', 'control2'])
),
});
See a stackblitz
CodePudding user response:
Simple problem :-)
The parameter for adding validators to a form via the Formbuilder is named "validators" instead "Validators".
newFWXForm = this.fb.group(
{
...
},
{
validators: this.atleastOnePortValue("icmp", "tcpPorts", "udpPorts"),
}
);
The rest of the code looks fine, however you should also check for empty string instead null
only, cause when user empties a feld it will not set to null
. null
is only the initial value of the form