Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 Pass parameter to a validator function

I have an array in my formcomponent class and want to be able to pass that array to a validator function. When adding multiple validators to the form, I am using Validators.compose function. This only accepts the name of the validator function though, and not any parameters to pass. Is it possible to add parameters to the function calls inside of the "compose" function?

export class ClientFormComponent
{
    clientForm: ControlGroup;
    npi: AbstractControl;
    name: AbstractControl;

    constructor(private _clientService: ClientService, _fb: FormBuilder) {
        this.clientForm = _fb.group({ 'name': ['', Validators.compose([Validators.required])], 'npi': ['', Validators.compose([Validators.required, npiNumValidator, Validators.maxLength(10), Validators.minLength(10)])]});
        this.name = this.clientForm.controls['name'];
        this.npi = this.clientForm.controls['npi'];
    }
    
    @Input() clientList;
    active = true;   
   
    onSubmit(value: Client) {
        this._clientService.addDeleteClient(value, true)
            .subscribe(
            client => this.clientList.push(client));        
    }    
}

function npiNumValidator(control: Control): { [s: string]: boolean } {
    if (isNaN(control.value)) {
        return { npiNAN: true };
    }
}

Thanks for any help!

like image 956
Bohms27 Avatar asked May 09 '16 15:05

Bohms27


3 Answers

If you need to reference dynamic data from the class you can pass an object within the parameter instead of a primitive.

Example:

  valParams = {
    gte: 10
  }
  constructor(protected _fb:FormBuilder) { 
    this.numForm = _fb.group({
      num: ['', gte(this.valParams)]
    });
  }

Validation Function:

export function gte(valParams: {gte:number}): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    let val: number = +control.value;
 
    if (isNaN(val)) return { 'gte': true }   
    if (val <= +valParams.gte) return { 'gte': true }

    return null;
  }
}

Since you're passing an object JavaScript will reference the object in memory rather than an immutable primitive.

PS: As a bonus since you're passing the object reference, you can update the object directly from the validation function which can then be read by the component class.

like image 126
OliviaLynn Avatar answered Sep 20 '22 13:09

OliviaLynn


Is it possible to add parameters to the function calls inside of the "compose" function?

Validator Declaration: straight out of Angular Code

/* Validator that requires controls to have a value of a minimum length. */

static minLength(minLength: number): ValidatorFn {
    return (control: modelModule.AbstractControl): {[key: string]: any} => {
      if (isPresent(Validators.required(control))) return null;
      var v: string = control.value;
      return v.length < minLength ?
                 {"minlength": {"requiredLength": minLength, "actualLength": v.length}} :
                 null;
    };
  }

Usage:

Validators.compose([Validators.minLength(4)]

NOTE: to understand it better, see How do JavaScript closures work?

like image 14
Ankit Singh Avatar answered Oct 16 '22 01:10

Ankit Singh


Just move it to a class

class NpiNumValicator {
  constructor(private someField: someType) {}

  npiNumValidator(control: Control): { [s: string]: boolean } {
    if (isNaN(control.value)) {
        return { npiNAN: true };
    }
  }
}

then use it like

this.clientForm = _fb.group({ 'name': ['',
    Validators.compose([Validators.required])], 'npi': ['', 
    Validators.compose([Validators.required, 
        new NpiNumValidator(someArg).npiNumValidator, 
        Validators.maxLength(10), Validators.minLength(10)
    ])
]});

to be able to use this within npiNumValidator you can use

var npiNumVal = new NpiNumValidator(someArg);
this.clientForm = _fb.group({ 'name': ['',
    Validators.compose([Validators.required])], 'npi': ['', 
    Validators.compose([Validators.required, 
        npiNumVal.npiNumValidator.bind(npiNumVal), 
        Validators.maxLength(10), Validators.minLength(10)
    ])
]}); 
like image 12
Günter Zöchbauer Avatar answered Oct 16 '22 02:10

Günter Zöchbauer