Search code examples
angularecmascript-6angular-reactive-formsarrow-functionsangular2-form-validation

Set dynamic ValidationFn in reactive form formgroup


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.


Solution

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