I'm writing a directive to enforce maxlength on a textarea field (HTML version < 5). I'm using AngularJS. As such, I want to get it done in a correct AngularJS manner. However, when I do it "Angularesque" as I perceive it, I can't quite get it to work completely.
(function () {
'use strict';
var myAppModule = angular.module('myApp', []);
myAppModule.controller('MyController', function($scope) {
$scope.textareaText = "";
});
myAppModule.directive('myMaxlength', ['$compile', '$log', function($compile, $log) {
return {
priority: 10000,
restrict: 'A',
require: 'ngModel',
compile: function (elem, attrs) {
elem.attr("ng-trim", "false");
return function(scope, linkElem, linkAttrs, ctrl) {
var maxlength = parseInt(linkAttrs.myMaxlength, 10);
ctrl.$parsers.push(function (value) {
$log.info("In parser function value = [" + value + "].");
if (value.length > maxlength)
{
$log.info("The value [" + value + "] is too long!");
value = value.substr(0, maxlength);
ctrl.$setViewValue(value);
ctrl.$render();
$log.info("The value is now truncated as [" + value + "].");
}
return value;
});
};
}
};
}]);
})();
This nearly works (see the JSFIDDLE here Note: This fiddle has since been updated with the chosen solution below, but the code above still exhibits the problem noted here.). It correctly limits characters going to the model, and renders that back to the display. However, you can continue to enter spaces to exceed the specified maxlength. The extra spaces don't get into the model, but they clutter the display. I believe this has something to do with ng-trim. As you can see (in the code snippet) I'm setting the attribute in the compile function, but it's too late by then. Some suggest manually calling compile within your compile function to force AngularJS to recognize the dynamically-added attribute, but that "appears" to create another copy and doesn't fix the display problem. Putting ng-trim="false" on the textarea element works, but I want a clean solution where all the user needs to do is add one attribute specifying the max length.
Here is another example (see the JSFIDDLE here) that is not quite as "Angularesque" in my opinion but get's the job done.
(function () {
'use strict';
var myAppModule = angular.module('myApp', []);
myAppModule.controller('MyController', function($scope) {
$scope.textareaText = true;
});
myAppModule.directive('myMaxlength', ['$log', function($log) {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
var maxlength = parseInt(attrs.myMaxlength, 10);
$log.info("maxlength=[" + maxlength + "]");
elem.bind('keydown', function (event) {
$log.info("elem.val().length=[" + elem.val().length + "]");
if (elem.val().length >= maxlength)
{
// Void event Except backspace
if (event.keyCode != 8){
event.preventDefault();
}
}
});
}
};
}]);
})();
So, what's a truly "Angularesque" way to implement maxlength on a textarea field? Thank you in advance!
You can use ngMaxlength argument on an input field in your html file (documentation here: https://docs.angularjs.org/api/ng/directive/input)
For example
<input type="text" ng-model="myRestrictedText" ng-maxlength="10"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With