Directive for directive communication in AngularJS
So, I have this filter directive:
app.directive('filter', function(){ return { restrict: 'E', transclude: true, scope: { callFunc: '&' }, template: ' <div>' + ' <div ng-transclude></div>' + ' </div>', controller: function($scope, $element, $attrs){ this.getData = function() { $scope.callFunc() } } } }); app.directive('positions', function(){ return { require: '^filter', scope: { selectedPos: '=' }, template: ' Positions: {{selectedPos}}' + ' <ul>' + ' <li ng-repeat="pos in positions">' + ' <a href="#" ng-click="setPosition(pos); posRegData()">{{pos.name}}</a></a>' + ' </li>' + ' </ul>', controller: function($scope, $element, $attrs){ $scope.positions = [ {name: '1'}, {name: '2'}, {name: '3'}, {name: '4'}, {name: '5'} ]; $scope.selectedPos = $scope.positions[0].name; $scope.setPosition = function(pos){ $scope.selectedPos = pos.name; }; }, link: function(scope, element, attrs, filterCtrl) { scope.posRegData = function() { filterCtrl.getData(); } } } })
And the controller:
app.controller('keyCtrl', ['$scope', function($scope) {
var key = this;
key.callFunc = function() {
key.value = key.selectedPos;
console.log(key.selectedPos)
}
}]);
The main question is: why does key.selectedPos
the controller get the correct value only on the second click?
Here is a plunker copying my problem.
One way to do this is to send a parameter when called callFunc()
Then I update the func in ctrl: key.callFunc = function(filterParams)
but also, I update the passed methodcall-func="key.callFunc(filterParams)
Then in filter directive
I change the getData method to:
this.getData = function(val) {
$scope.callFunc({filterParams: val})
}
In positions directive
passing the value that I need:
scope.posRegData = function() {
filterCtrl.getData({position: scope.selectedPos});
}
Finally, in keyCtrl
I get the following value:
key.callFunc = function(filterParams) {
key.value = filterParams.position;
console.log(filterPrams.position)
}
Here is a plunker demonstrating this attempt.
The question in this case is if this is a good way to do this, keeping this in mind in a very large application.
This is because isolated areas are at work. The parent area (controller in your case) will be updated after running the digest loop, which ng-click
is called after your function callFunc
. This way you can put your callFunc
code in $timeout
and it will work (but will trigger another digest loop).
Another solution would be to put the value into an object, so when the object changes, the controller (having a reference) will immediately see the update:
In the controller:
key.selectedPos = { value: {}};
key.callFunc = function() {
key.value = key.selectedPos.value;
console.log(key.selectedPos.value)
}
In the directive:
$scope.selectedPos.value = $scope.positions[0].name;
$scope.setPosition = function(pos){
$scope.selectedPos.value = pos.name;
};
See plunker .