I have a AngularJs directive that creates a property and callback function on its isolated scope:
.directive('testButton', [function () {
return {
restrict: 'A',
controller: 'TestDirectiveController as vmDirective',
scope: {
myCallBack:'&myCallBack',
myVariable: '=myVariable'
},
template: function (element, attrs) {
return '<button data-ng-click="vmDirective.onButtonClicked(2)">Set myVariable = 2</button>';
}
};}])
In the directive a button gets clicked and it executes the onButtonClicked
function. This then sets a scope variable and calls the $scope.myCallBack
function.
The callBack function gets executed and does the following:
console.log($scope.linkedVariable);
The problem is the $scope.linkedVariable
has not yet been updated and at that stage the $scope.linkedVariable
is still the previous value.
When I wrap the above code in a setTimeout
the correct value is retrieved: setTimeout(function(){console.log($scope.linkedVariable)}, 2000);
My Question is, how to properly pass the value to the onCallBack
function.
Please see full code example below:
angular.module('application',[])
.directive('testButton', [function () {
return {
restrict: 'A',
controller: 'TestDirectiveController as vmDirective',
scope: {
myCallBack:'&myCallBack',
myVariable: '=myVariable'
},
template: function (element, attrs) {
return '<button data-ng-click="vmDirective.onButtonClicked(2)">Set myVariable = 2</button>';
}
};
}])
.controller("TestDirectiveController", ['$scope', function($scope){
var self = this;
self.onButtonClicked = function(value){
$scope.myVariable = value;
$scope.myCallBack();
};
}])
.controller("TestController", ['$scope', function($scope){
var self = this;
$scope.linkedVariable = null;
self.onCallBack = function(){
console.log($scope.linkedVariable);
setTimeout(function(){console.log($scope.linkedVariable)}, 2000);
};
}])
HTML:
<div data-ng-controller="TestController as vm">
<div data-test-button="" data-my-call-back="vm.onCallBack()" data-my-variable="linkedVariable"></div>
</div>
jsfiddle: http://jsfiddle.net/ff5ck0da/1/
I found a more acceptable/correct way of overcoming my problem thanks to http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters.
Instead of accessing the
$scope.linkedVariable
in the controller, I now accept the value as a parameter to the function.To get this to work I had to change the function declaration in the HTML to:
data-my-call-back="vm.onCallBack"
The controller function declaration:
the directive can then call the function like:
Please see a updated JSFiddle: http://jsfiddle.net/ff5ck0da/9/
You can even change the settimeout to
this will push the resolution of the variable to the bottom of the async stack. And thus evaluate after the angular digest loop is done ( in essence the variable value is set)
If you dont want to use settimeout you can use this:
here you are essentially telling angular to not use a copy but the actual parent variable.