
Question:
I have a complex control (button clicks, dropdowns, etc) that builds a string. So every button click/dropdown selection calls a scope function that in turn updates a scope variable that holds my result.
I bind this scope variable to a hidden field in the UI:
<input type="hidden" ng-model="MyComplexString" custom-validation ng-value="MyComplexString" />
However, when the controller function updates <em>MyComplexString</em>, <em>custom-validation</em> isn't triggered.
I tried changing the input type to text, and indeed <em>MyComplexString</em> gets updated, however, <em>custom-validation</em> still doesn't fire.
If I type in the textbox however, <em>custom-validation</em> fires as expected.
Research shows that AngularJs listens for 'input' events fired on DOM elements, but the controller function doesn't fire those events on the inputs bound to scope variables after changing the scope variables. So I need to do this manually.
I hope this makes sense. Any ideas would be appreciated.
Thank you!
EDIT = Adding the implementation of the validation directive (implementation only checks whether something starts with a 'comma'.
.directive("customValidation", function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, ele, attrs, ctrl) {
ctrl.$parsers.unshift(function(value) {
var valid = false;
if (value) {
// test and set the validity after update.
valid = value.charAt(0) == ',';
ctrl.$setValidity('customValFlag', valid);
}
return valid ? value : undefined;
});
}
};
})
Answer1:Something you can do is to use a $watch
within your directive so it is reusable. See the answer <a href="https://stackoverflow.com/a/16308483/2279020" rel="nofollow">here</a>
Essentially, within your link function you can $watch
the attrs.ngModel
, which catches any changes. Your link
function would change to something like this:
link: function (scope, element, attrs) {
scope.$watch(attrs.ngModel, function (newVal) {
//Do custom validation here
});
}
See working JSFiddle I forked <a href="http://jsfiddle.net/jLz1dzty/" rel="nofollow">here</a> with two simple inputs and a hidden input using the directive that writes every change to the console
<strong>Edit:</strong> You might want to check for newVal and oldVal being equal to ignore the initialization call, which would look like this:
link: function (scope, element, attrs) {
scope.$watch(attrs.ngModel, function (newVal, oldVal) {
if(newVal !== oldVal) {
//Do custom validation here
}
});
}