Reputation: 15015
I'm having a binding timing issue with my AngularJS directive. Its controller looks like this:
controller: function($element, $scope)
{
$element.find("input").bind("blur", function()
{
SendUpdate();
});
$scope.Subtract = function()
{
Add(-$scope.step);
}
$scope.Add = function()
{
Add($scope.step);
}
function Add(amount)
{
$scope.model = parseInt($scope.model) + parseInt(amount);
console.log("Model: " + $scope.model);
SendUpdate();
}
function SendUpdate()
{
$scope.$emit("ProcessUpdate");
}
}
Everything works properly thus far, and start at a value of 100 and adding 10, it prints out Model: 110, as expected. But, when the event is handled by the parent scope, which is providing the variable that model is bound to, it has not received the updated value by the time the event fires:
$scope.$on("ProcessUpdate", function()
{
console.log("MyValue: " + $scope.MyValue);
});
That prints out MyValue: 100, even though it's $scope.MyValue that is bound to the directive's model variable (I'm using the "=" binding character, too).
The value is, in fact, being updated. If I press a button that prints out the same exact thing:
console.log("MyValue: " + $scope.MyValue);
It prints the correct value of MyValue: 110. So it's clearly a timing issue. It looks like things are happening in this order:
What I need is for 4 to happen immediately after 1, because when the event is fired I need the parent scope to be up to date.
Is there a different way that I should be doing this? I don't want to pass the updated value via the event because any number of these directives could be firing and they need to all process the parent scope. I don't want to have to figure out what changed and inject it accordingly. I just want to fire the event after the parent scope has received the directive's new value.
Thank you.
Upvotes: 2
Views: 1784
Reputation: 84
Try the code below
$scope.$on("ProcessUpdate", function() {
$timeout(function() {
console.log("MyValue: " + $scope.MyValue);
});
});
Even though the timeout is zero, it does not execute until interpolation and DOM rendering is complete. That behavior is explained in more detail here:
http://ejohn.org/blog/how-javascript-timers-work/
Hope that works for you :)
Upvotes: 6
Reputation: 4880
The problem is you are using events (which are immediate) and two-way binding uses the Angular $digest
loop. How about instead of using $on
and $emit
you use a $watch
function instead?
In your directive, you would do this:
$scope.$watch("MyValue", function(newValue, oldValue) {
console.log("MyValue: " + $scope.MyValue);
});
And in your controller all you have to do is remove SendUpdate
.
Upvotes: 2