Reputation: 7531
I am working on a small project for Angular 2.0 using TypeScript. Right now to my understanding, Angular 2.0 does not have built-in validators for "min" and "max" tags. I understand how you can build a custom validator and attach it using FormBuilder
but I wish to see how to create a custom validator directive that I can attach on an attribute. The HTML looks like this:
<div class="unit">
<div class="label">Age (13 - 120):</div>
<div class="labelTarget">
<input id="ageFrm" min="13" max="120" type="number" required=""
ng-control="age" #age="form" [class.error]="!age.valid"
[(ng-model)]="ageValue"/> {{age.valid}}
</div>
</div>
Right now age.valid
is always true
because there are no validators for min
and max
. I tried creating my own. First the custom validation functions:
import {Control} from "angular2/angular2";
export class HealthAppCustomValidators {
static min(min: number): Function {
return (control: Control): {[key: string]: any} => {
var v: number = Number(control.value);
console.log("validating " + v + " against " + min);
return v < min ?
{"min": {"requiredMin": min, "actualMin": v}} :
null;
};
}
static max(max: number): Function {
return (control: Control): {[key: string]: any} => {
var v: number = Number(control.value);
return v > max ?
{"max": {"requiredMax": max, "actualMax": v}} :
null;
};
}
}
And next the directives (this is based on examining the source code):
import {Attribute, Control, Directive, forwardRef, Provider, NG_VALIDATORS} from "angular2/angular2";
import {HealthAppCustomValidators} from "./customValidators";
const MIN_VALIDATOR = new Provider(NG_VALIDATORS, {useExisting:
forwardRef(() => MinValidator), multi:true});
@Directive({
selector: '[min][ng-control],[min][ng-form-control],[min][ng-model]',
providers: [MIN_VALIDATOR]
})
export class MinValidator {
private _validator: Function;
constructor(@Attribute("min") min: string) {
console.log(min);
this._validator = HealthAppCustomValidators.min(Number(min));
}
validate(c: Control): {[key: string]: any} {
console.log("validate");
return this._validator(c);
}
}
However, whenever I actually import the directives the page load fails with the following error:
TypeError: validator is not a function
at http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:12990:24
at Array.reduce (native)
at Function.ListWrapper.reduce (http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:4206:19)
at http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:12989:44
at http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:12990:24
at Array.reduce (native)
at Function.ListWrapper.reduce (http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:4206:19)
at Control.validator (http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:12989:44)
at Control.AbstractControl.updateValidity (http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:18871:27)
at http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:14097:14
Any help with the correct way to do this without FormBuilder
is greatly appreciated:
Upvotes: 3
Views: 976
Reputation: 31787
As suggested by Jeremy,
the problem is solved since alpha 45 where they added support for Validator. The error message may be confusing though (you were providing a function, why didn't work?) but the commit message gives a clue
Currently, the only way for a directive to export a validator is by providing a function. This makes it ackward to write validators that depend on directive inputs. In addition to supporting functions as validators, classes implementing the Validator interface are supported too.
I couldn't find examples for custom validators in alpha 44 or below, so I can't say how they worked at that moment. And it's most likely they updated all their examples and working validators to work with alpha 45+.
Anyway, this was solved by upgrading angular2, to the most recent version (alpha 48 is the latest one by the way, I said alpha 47 in the comment, my bad) although it was required at least alpha 45.
Upvotes: 2