runtimeZero
runtimeZero

Reputation: 28116

Custom Validation in Angular2 forms

Following the example here :

https://angular.io/docs/ts/latest/guide/forms.html

My form looks like:

<input type="text" class="form-control" id="name"
               required
               [(ngModel)]="model.name" name="name"
               #name="ngModel" >
        <div [hidden]="name.valid || name.pristine" 
             class="alert alert-danger">

I want to add some custom validation to this form. I did find some advise about using ngFormModel and FormBuilders and Validation class, however I believe these are outdated and no longer recommended

( http://almerosteyn.com/2016/03/angular2-form-validation-component)

My question then is how do I add custom validation.

In angular 1.x I used to add functions to ngModel.$parsers and ngModel.$formatters pipeline. What is the equivalent in angular 2 ?

Upvotes: 6

Views: 1432

Answers (2)

snehal badhe
snehal badhe

Reputation: 102

Try this:

import { CustomValidators } from 'ng2-validation';

ngOnInit() {
   const Email = new FormControl('', [Validators.required, CustomValidators.email]);
}

Upvotes: 0

Carlos Mermingas
Carlos Mermingas

Reputation: 3892

I do it by using a model-driven approach, instead of template-driven. For example:

Form

<form [formGroup]="myForm">
    <label for="id-name">Name</label>
    <input type="text" id="id-name" formControlName="name">
    <label for="id-age">Age</label>
    <input type="text" id="id-age" formControlName="age">
</form>

Component

export class MyComponent implements OnInit {
    myForm:FormGroup;

    ngOnInit() {
        let fuv = FormUtils.validators;

        this.myForm = this.formBuilder.group({
            name: ['', Validators.required],
            age: ['', [Validators.required, fuv.isNumber]],
        });
    }
}

FormUtils

type ValidatorResult = {[key:string]:any};

function _isNumber(control:AbstractControl):ValidatorResult {
    let v = control.value;
    if (isPresent(v) && !isNumber(v) && !isEmptyString(v)) {
        return {'isNumber': false};
    }
    return null;
}

export class FormUtils {
      static validators = {
        isNumber: _isNumber
      }
}

Here, isPresent, isNumber, and isEmptyString are pretty straightforward:

isPresent(obj) --> return obj !== undefined && obj !== null;
isNumber(obj) --> return (typeof obj === 'number' && !isNaN(obj));
isEmptyString(obj) --> return obj === '';

Currently, Angular 2 gives you four useful validators: required, minLength, maxLength, and pattern. The last one is pretty powerful. You can write your own validators following a pattern similar to _isNumber above. If your validator requires a parameter (e.g. lessThan), then you can use a pattern similar to this:

function lessThan(maxVal:number):ValidatorFn {
    return (control:AbstractControl):ValidatorResult => {
        let value = control.value;

        if (isPresent(value) && !isEmptyString(value) && isNumber(value) && parseInt(value) >= maxValue) {
            return {'lessThan': {'maxValue': maxValue, 'actual': value}};
        }

        return null;
    };
}

I understand that this approach (model-driven) is different from the form that you posted in your question (template-driven). I hope it helps anyway.

Upvotes: 2

Related Questions