I'm somewhat new to Angular, so feedback on alternative approaches is certainly welcome.
I have created a directive called "serverMaxLengths". When the directive is placed on an ng-form, it will fetch database fields lengths from a REST API and then will walk the contents of all input elements contained within the form controller, and will set the "maxlength" attribute accordingly. The directive is as follows:
myApp.directive('serverMaxLengths', function ($log,$http,$compile) {
return {
restrict: 'A',
require: '^form',
link: function (scope, elem, attrs, formController) {
if (!formController) return;
var httpConfig = {
method: 'GET',
url: myAppRestURL + "/validator-rest?action=getDBFieldLengths"
};
$http(httpConfig)
.success(function (data, status, headers, config) {
if (typeof data.isValid != 'undefined') {
if(data.isValid){
var inputElem = elem.find('input');
angular.forEach(inputElem, function (value, key) {
var thisElement = angular.element(value);
if (typeof thisElement[0] !== 'undefined') {
if(typeof data.dbFieldLengths[thisElement[0].id] !== 'undefined'){
if(data.dbFieldLengths[thisElement[0].id] > 0){
thisElement.prop("maxlength", data.dbFieldLengths[thisElement[0].id]);
thisElement.prop("ng-maxlength", data.dbFieldLengths[thisElement[0].id]);
thisElement.prop("ng-minlength", 0);
$compile(thisElement)(scope);
}
}
}
});
}else{
...
}
}else{
...
}
}).error(function (data, status, headers, config) {
...
});
}
};});
This works. Insofar as I understand, $compile is replacing the existing element(s) when the directive is executed.
I'm wondering what a better "Angular" way of achieving this might be? I wanted a very simple solution that doesn't require the directive to be placed on any of the actual input elements(I want everything to happen in one go).
Lastly, one of the fields that is getting the max length set has a UI Bootstrap Typeahead directive assigned to it. Prior to the application of the "maxlength", the directive works as expected. However, post application of the "maxlength" being set on the field via the aforementioned method, type ahead renders a "TypeError: Cannot read property 'length' of undefined" error when the input looses focus(otherwise it works). This has me concerned about this approach, and what's happening behind the scenes.
*Note: The type ahead error is resolved by doing:
$compile(thisElement.contents())(scope);
Instead of:
$compile(thisElement)(scope);
Thanks for any feedback/suggestions/thoughts.