You are missing a scope.$apply
when you handle the JS events in your directive.
The event handling happens in pure JS, outside the angular context and when you invoke the function on the parent scope, you are invoking it as you would invoke a function on any other plain JS object. Keeping plain JS objects instead of creating their own object hierarchies where they could intercept function calls is a design choice which Angular made different from, say, ember
.
The value does change on the scope, it is just that Angular is not aware of it. The next time a $digest
loop is triggered by anything (say a different button click with an ng-click
), the change would show up. What we can do, however, is to make sure that the $digest
loop is triggered by explicitly calling scope.$apply()
.
The fix is this:
element.bind("blur change keyup", function() {
// This will tell Angular to rerun the $digest loop
// as we are changing some variables which Angular
// should be informed about.
scope.$apply(function () {
var val = element.find("input").val();
var oldval = scope.values[scope.field.name];
if (oldval !== val && isValid(val))
scope.set_value(scope.field.name,val);
//else
// scope.set_value(scope.field.name,undefined);
});
});
Working demo: http://jsbin.com/inoKOVU/1/edit