Reputation: 1354
I'm trying to use custom validator to compare if the end time is greater than the start time.
code:
function timeValidator(): ValidatorFn {
return (control: AbstractControl): { [key: string]: boolean } | null => {
if (control.value !== undefined && (isNaN(control.value) || control.get('fromTime').value > control.get('toTime').value)) {
return { 'ageRange': true };
}
return null;
};
}
From formgroup
toTime: new FormControl(null, [Validators.required, timeValidator(this.fromTime,this.toTime)]),
I'm getting a error once I run this like: Cannot read property 'value' of null
on the line if (control.value !== undefined && (isNaN(control.value) || control.get('fromTime').value > control.get('toTime').value))
I need some help in fixing this. Thank you
Upvotes: 0
Views: 2082
Reputation: 1
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
export function uniqueChildConditionValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (!Array.isArray(control.value)) {
return null; // If the control value is not an array, no validation needed
}
const mainObjects = control.value;
// Iterate over each main object to check its child conditions
for (let i = 0; i < mainObjects.length; i++) {
const mainObj = mainObjects[i];
// Ensure the current main object has child conditions to check
if (mainObj.childCondition && mainObj.childCondition.length > 0) {
const seenChildConditions = new Set<string>();
// Check each child condition for duplication
for (const child of mainObj.childCondition) {
const childConditionKey = `${child.field}-${child.condition}-${child.conditionText}`;
// Check if the child condition matches the parent condition
const parentConditionKey = `${mainObj.field}-${mainObj.condition}-${mainObj.conditionText}`;
if (childConditionKey === parentConditionKey) {
return { conditionMismatch: `Child condition in main object ${i + 1} matches the parent condition.` };
}
// Check if the child condition has been seen before (duplicate check)
if (seenChildConditions.has(childConditionKey)) {
return { conditionMismatch: `Child condition ${childConditionKey} is duplicated in main object ${i + 1}.` };
}
// Add the child condition to the set of seen conditions
seenChildConditions.add(childConditionKey);
}
}
}
return null; // No issues found
};
}
Upvotes: 0
Reputation: 1
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
export function uniqueChildConditionValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (!Array.isArray(control.value)) {
return null; // If the control value is not an array, no validation needed
}
const mainObjects = control.value;
// Iterate over each main object to check its child conditions
for (let i = 0; i < mainObjects.length; i++) {
const mainObj = mainObjects[i];
// Ensure the current main object has child conditions to check
if (mainObj.childCondition && mainObj.childCondition.length > 0) {
const seenChildConditions = new Set<string>();
// Check each child condition for duplication
for (const child of mainObj.childCondition) {
const childConditionKey = `${child.field}-${child.condition}-${child.conditionText}`;
// Check if the child condition matches the parent condition
const parentConditionKey = `${mainObj.field}-${mainObj.condition}-${mainObj.conditionText}`;
if (childConditionKey === parentConditionKey) {
return { conditionMismatch: `Child condition in main object ${i + 1} matches the parent condition.` };
}
// Check if the child condition has been seen before (duplicate check)
if (seenChildConditions.has(childConditionKey)) {
return { conditionMismatch: `Child condition ${childConditionKey} is duplicated in main object ${i + 1}.` };
}
// Add the child condition to the set of seen conditions
seenChildConditions.add(childConditionKey);
}
}
}
return null; // No issues found
};
}
Upvotes: 0
Reputation: 1
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
export function uniqueMainChildConditionValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (!Array.isArray(control.value)) {
return null; // Not an array, so we don't need to validate
}
const mainObjects = control.value;
for (let i = 0; i < mainObjects.length; i++) {
const mainObj = mainObjects[i];
// Check each main object's child conditions
if (mainObj.childCondition && mainObj.childCondition.length > 0) {
for (const child of mainObj.childCondition) {
if (
mainObj.field === child.field &&
mainObj.condition === child.condition &&
mainObj.conditionText === child.conditionText
) {
return { conditionMismatch: `Main object ${i + 1} has matching properties with a child condition.` };
}
}
}
// Check if the current main object matches any other main object
for (let j = 0; j < mainObjects.length; j++) {
if (i !== j) { // Ensure we are not comparing the same object
const otherMainObj = mainObjects[j];
if (
mainObj.field === otherMainObj.field &&
mainObj.condition === otherMainObj.condition &&
mainObj.conditionText === otherMainObj.conditionText
) {
return { conditionMismatch: `Main object ${i + 1} has matching properties with main object ${j + 1}.` };
}
}
}
}
return null; // No issues found
};
}
Upvotes: 0
Reputation: 3511
Your custom validator should be put at FormGroup level not FormControl level. Also you should pass the function in as an argument, meaning without the () brackets because timeValidator is a callback function. () tells the js engine to execute the function. But what you want is pass in the function as an argument, so it could be executed later.
either
constructor(private fb: FormBuilder){}
...
this.form = this.fb.group({
fromTime: [''],
toTime: ['']
}, { validator: timeValidator})
OR
form = new FormGroup({
toTime: new FormControl(null),
fromTime: new FormControl(null),
}, { validator: timeValidator})
Your custom validator also shouldn't be returning a function. It should be returning a name:boolean key-value pair. E.g. isEndGTStart: true or null if false
E.g.
export function timeValidator(fg: FormGroup){
const fromTime = fg.get("fromTime").value;
const toTime = fg.get("toTime).value;
return toTime > fromTime ? { isEndGTStart: true } : null
}
Upvotes: 1