I am working on the below validation directive, suggested to me in this answer:
MyBigAngularApp.directive("bkNgValidation", function ($compile) {
return {
priority: 10000,
terminal: true,
link: function (scope, element, attrs) {
var validationType = attrs.bkNgValidation;
window["addValidationFor_" + validationType](element);
// prevent infinite loop
element.removeAttr("bk-ng-validation");
$compile(element)(scope);
}
};
});
Then, when I apply this directive to an html element, in the form, bk-ng-validation="phoneNumber"
, my directive invokes this function:
function addValidationFor_phoneNumber(element) {
element.attr("ng-pattern", "/^[0-9]+$/");
element.attr("ng-minlength", 5);
element.attr("ng-maxlength", 8);
alert("yeah baby");
}
This addValidationFor_phoneNumber
is currently in the global namespace, just for my proof of concept, but I am looking to maybe use a revealing module to organize what could become quite a number of validation functions. Or is there some other pattern I should follow because I am working inside Angular? I suspect I could do something like declare a constant for the revealing module and inject it into the directive, but I thought I'd ask this question before going too far down the wrong road.
Indeed it is generally not recommended to use variables from the global scope in Javascript, and an absolute anti-pattern when working with AngularJS.
What you are looking for is a service
(or factory
, which does the same job in a slightly different syntax), which would be injected to your directive.
MyBigAngularApp.service('bkService', function() {
this.phoneNumber = function(element) { ... }
this.somethingElse = function(element) { ... }
});
And your directive becomes:
// Note how bkService is injected to the directive in this first line
MyBigAngularApp.directive("bkNgValidation", function ($compile, bkService) {
return {
priority: 10000,
terminal: true,
link: function (scope, element, attrs) {
var validationType = attrs.bkNgValidation;
bkService[validationType](element);
// prevent infinite loop
element.removeAttr("bk-ng-validation");
$compile(element)(scope);
}
};
});
Now if the only directive that will use this service is that one, you don't really need to create a service but can simply wrap all these functions as private methods from bkNgValidation:
MyBigAngularApp.directive("bkNgValidation", function ($compile) {
var validations = {
phoneNumber: function(element) { ... }
somethingElse: function(element) { ... }
};
return {
priority: 10000,
terminal: true,
link: function (scope, element, attrs) {
var validationType = attrs.bkNgValidation;
validations[validationType](element);
// prevent infinite loop
element.removeAttr("bk-ng-validation");
$compile(element)(scope);
}
};
});