0

I'm trying to create a very generic\dynamic reactive form which can use a custom Validation Function for a formgroup (to compare 2 dates). The function can actually be any validation function which is of type ValidatorFn:

export interface ValidatorFn {
(control: AbstractControl): ValidationErrors | null;
}

Here is the root problem:
I'm defining the function in a kind of configuration file and I init the reactive form with it (receiving the function as a parameter) and set the formGroup with the validationFn. Here is the function:

customValidationFunction : ValidatorFn = (group : FormGroup) : ValidationErrors | null => 
{
  return (/*control : AbstractControl*/)/*:{[key: string] : any} | null*/ => 
  {
    if (group.controls["CreatedDateFormatFrom"] && group.controls["CreatedDateFormatTo"])
    {
      let from : AbstractControl = group.get("CreatedDateFormatFrom");
      let to : AbstractControl = group.get("CreatedDateFormatTo");
      const inValid = from && to &&  to.value < from.value;
      return inValid ? {'invalidDates' : true } : null;   
    }
    return null;
  }
}

Now, in the "customize\generic\dynamically created" reactive form initiation, I set the function (or some functions):

initForm(formGroupCustomValidation? : ValidatorFn[] )
{
   let group: any = {};
   //Here I initiate the group with FormControls, for example:
   group[<fieldName>] = new FormControl(<some value> || ''); 
   //This is where the custom validation function comes:
   if (formGroupCustomValidation)
   {
      this.form = new FormGroup(group, {validators:                
                                        formGroupCustomValidation });  
   }
   this.form.valueChanges.subscribe(values => {
     console.log(values);
     this.formValid();
   })
}

I'm sorry for the "blurry" code, but this is due to the dynamically created form. The problem is how to pass and execute the function with the group : FormGroup parameter ? I tend to believe that I have some problem with the function definition\scope, etc. I can't see the function body triggered, when trying to debug the function. Please support.

1

2 Answers 2

2

You don't have to return another function since you are not passing extra arguments, that would be enough:

  customValidationFunction: ValidatorFn = (group: FormGroup) => {
    const from: AbstractControl = group.get('CreatedDateFormatFrom');
    const to: AbstractControl = group.get('CreatedDateFormatTo');

    if (from && to) {
      const inValid = from && to && to.value < from.value;
      return inValid ? {'invalidDates': true} : null;
    }
    return null;
  }

Edit 1:

Ok I missed a point a bit since you want to pass this first group to second one and perform validation on controls from first one.

That should work:

    const group = new FormGroup({
      CreatedDateFormatFrom: new FormControl(),
      CreatedDateFormatTo: new FormControl()
    });

    const group2 = new FormGroup({anotherGroup: group}, this.customValidationFunction(group));

    group.controls.CreatedDateFormatFrom.setValue('11-12-2018');
    group.controls.CreatedDateFormatTo.setValue('11-11-2018');

  customValidationFunction: ValidatorFn = (group: FormGroup) => {
    return () => {
      const from: AbstractControl = group.get('CreatedDateFormatFrom');
      const to: AbstractControl = group.get('CreatedDateFormatTo');

      if (from && to) {
        const inValid = from && to && to.value < from.value;
        return inValid ? {'invalidDates': true} : null;
      }
      return null;
    };
  }
Sign up to request clarification or add additional context in comments.

1 Comment

You are right. I just found out and did it almost like this.
0

OK, I found a solution just as @Buczkowski metioned. Here is my corrected code (left code as commented out on purpose - to show the diff):

customValidationFunction: ValidatorFn /*: ValidatorFn*/ = (group : FormGroup) /*: 
 ValidationErrors | null*/ => 
{
/*return (control : AbstractControl):{[key: string] : any} | null => 
{*/
   if (group.controls["CreatedDateFormatFrom"] && 
      group.controls["CreatedDateFormatTo"])
   {
     let from : AbstractControl = group.get("CreatedDateFormatFrom");
     let to : AbstractControl = group.get("CreatedDateFormatTo");
    const inValid : boolean = from && to && from.value && to.value && to.value < from.value;
    return inValid ? {'invalidDates' : true } : null;   
  }
  return null;
/*}*/

}

Comments

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.