问题
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/
回答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:
self.onCallBack = function(myVariable){
console.log(myVariable);
};
the directive can then call the function like:
self.onButtonClicked = function(value){
$scope.myCallBack()(value);
};
Please see a updated JSFiddle: http://jsfiddle.net/ff5ck0da/9/
回答2:
You can even change the settimeout to
setTimeout(function(){console.log($scope.linkedVariable)}, 0);
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:
self.onCallBack = function(){
var accessor = $parse($scope.linkedVariable);
$scope.value = angular.copy(accessor($scope.$parent));
console.log($scope.linkedVariable);
};
here you are essentially telling angular to not use a copy but the actual parent variable.
来源:https://stackoverflow.com/questions/31181668/pass-parameter-to-angularjs-controller-function-from-directive