Defining custom control validators
Another data property defined in the Developer
class is the email
field. Let’s add an input field for this property. Above the button in the preceding form, add the following markup:
<div class="form-group"> <label class="control-label" for="emailInput">Email</label> <div> <input id="emailInput" class="form-control" type="text" ngControl="email" [(ngModel)]="developer.email"/> </div> </div>
We can think of the [(ngModel)]
attribute as an alternative to the ng-model
directive from AngularJS 1.x. We will explain it in detail in the Two-way data binding with Angular 2 section.
Although Angular 2 provides a set of predefined validators, they are not enough for all the various formats our data can live in. Sometimes, we’ll need custom validation logic for our application-specific data. For instance, in this case, we want to define an e-mail validator. A typical regular expression, which works in general cases (but does not cover the entire specification that defines the format of the e-mail addresses), looks as follows: /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/
.
In ch6/ts/step-1/add_developer.ts
, define a function that accepts an instance of Angular 2 control as an argument and returns null
if the control’s value is empty or matches the regular expression mentioned earlier, and { 'invalidEmail': true }
otherwise:
function validateEmail(emailControl) { if (!emailControl.value || /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/.test(emailControl.value)) { return null; } else { return { 'invalidEmail': true }; } }
Now, from the modules angular2/common
and angular2/core
import NG_VALIDATORS
and Directive
, and wrap this validation function within the following directive:
@Directive({ selector: '[email-input]', providers: [provide(NG_VALIDATORS, { useValue: validateEmail, multi: true })] }) class EmailValidator {}
In the preceding code, we defined a single multiprovider for the token NG_VALIDATORS
. Once we inject the value associated with this token, we’ll get an array with all the validators attached to the given control
The only two steps left in order to make our custom validation work are to first add the email-input
attribute to the e-mail control:
<input id="emailInput"
class="form-control"
email-input
type="text" ngControl="email"
[(ngModel)]="developer.email"/>
Next, to add the directive to the list used by the component AddDeveloper
directives:
@Component({
selector: 'dev-add',
templateUrl: './add_developer.html',
styles: [`
input.ng-touched.ng-invalid {
border: 1px solid red;
}
`],
directives: [FORM_DIRECTIVES, EmailValidator],
providers: [FORM_PROVIDERS]
})
class AddDeveloper {…}