@seges/angular-validators
Version:
TypeScript 1.8.10
110 lines (98 loc) • 3.89 kB
text/typescript
import { IValidator } from "./IValidator";
export class AngularValidationDirective<TValidator extends IValidator<TDependencies>, TDependencies> {
validator: IValidator<TDependencies>;
/**
* Angular validation wrapper.
* Set angular specific setup to use custom validation directive.
*
* Example usage:
* const validator = new AngularValidationDirective(CustomValidator);
* angular
* .module(moduleName, [])
* .directive("isCustomValid", validator.factory);
*
* @param validator The validator class implementing IValidator.
* @param directiveName The directive name in pascal casing.
*/
constructor(validator: { new (): TValidator; }, private directiveName: string) {
if (!validator) {
throw Error("Angular validation directive is dependent on IValidator implementation.");
}
if (!directiveName) {
throw Error("Angular validation directive must have a directive name");
}
this.validator = new validator();
}
/**
* Link method for Angular directive. Called after the view is loaded.
*/
link = (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ngModel: ng.INgModelController) => {
this.initNgModel(ngModel, (value: string) => this.validateInput(value, ngModel, attrs));
attrs.$observe(this.directiveName, () => {
this.validateInput(ngModel.$viewValue, ngModel, attrs);
});
}
/**
* Validate value against validator.
* @param value The value to validate.
*/
validateInput = (value: string, ngModel: ng.INgModelController, attrs: ng.IAttributes): string => {
if (!value) {
this.setValidity(true, ngModel);
return value;
}
if (this.validator.isValid(value, attrs)) {
this.setValidity(true, ngModel);
return value;
}
this.setValidity(false, ngModel);
return value;
}
/**
* Factory method to register directive with Angular.
*
* Example:
* const integerValidatorName = "isInteger";
* const integerValidator = new AngularValidationDirective(IntegerValidator, integerValidatorName);
* module.directive(integerValidatorName, () => integerValidator.factory());
*
* If validator has dependencies, they can be injected from Angular like this:
* const dateValidValidatorName = "dateFormat";
* const dateValidValidator = new AngularValidationDirective<DateValidator, IDateValidatorDeps>(
* DateValidator,
* dateValidValidatorName
* );
* module.directive(dateValidValidatorName,
* (moment: moment.MomentStatic, dateFormat: string) => dateValidValidator.factory({
* moment,
* dateFormat,
* })
* );
*
* @param dependencies Optional dependency object to set on validator.
*/
factory(dependencies?: TDependencies): ng.IDirective {
if (this.validator.setDependencies && dependencies) {
this.validator.setDependencies(dependencies);
}
return {
link: this.link,
require: "ngModel",
scope: false,
};
}
/**
* Set ngModel validity.
* @param isValid The validity.
*/
setValidity = (isValid: boolean, ngModel: ng.INgModelController): void => {
ngModel.$setValidity(this.directiveName, isValid);
}
/**
* Initialize ngModel with validator.
*/
private initNgModel = (ngModel: ng.INgModelController, validatorMethod: ng.IModelParser): void => {
ngModel.$parsers.unshift(validatorMethod);
ngModel.$formatters.push(validatorMethod);
}
}