0

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

3
  • 1
    can you share the code on stackblitz.com Commented Jun 7, 2019 at 11:40
  • You are calling the validator instead of passing the function as a parameter Commented Jun 7, 2019 at 12:07
  • Thank you, an example would be great to learn.@AvinKavish Commented Jun 7, 2019 at 12:35

4 Answers 4

1

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
}
Sign up to request clarification or add additional context in comments.

Comments

0
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
  };
}

Comments

0
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
  };
}

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0
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
  };
}

1 Comment

Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.