Reputation: 1201
I am trying to let one child directive to tell its sibling some information has been updated.
I have this markup:
<rp-nav>
<rp-nav-item cat="1"></rp-nav-item>
<rp-nav-item cat="2"></rp-nav-item>
<rp-nav-item cat="3"></rp-nav-item>
<rp-flyout></rp-flyout>
</rp-nav>
<hr>
<rp-nav>
<rp-nav-item cat="one"></rp-nav-item>
<rp-nav-item cat="two"></rp-nav-item>
<rp-nav-item cat="three"></rp-nav-item>
<rp-flyout></rp-flyout>
</rp-nav>
I am using events in this way:
angular.module('rpNavItem', [])
.directive('rpNavItem', function() {
return {
restrict: 'E',
controller: function($scope) {},
controllerAs: 'ctrl',
bindToController: true,
// scope: true,
template: function(el, attrs) {
return '<div>Item ' + attrs.cat + '</div>';
},
link: function(scope, el, attrs, ctrl) {
el.on('click', function(){
scope.$broadcast('selectedCat', attrs.cat);
});
}
};
});
angular.module('rpFlyout', []).directive('rpFlyout', function() {
return {
restrict: 'E',
controllerAs: 'ctrl',
bindToController: true,
// scope:true,
controller: function($scope) {},
template: '<p style="background-color: lightblue">{{category}}</p>',
link: function(scope) {
scope.$on('selectedCat', function(event, value){
scope.category = value;
scope.$digest();
console.log(value);
});
}
};
});
The problem is that every time I click on one item, both flyouts get update and I just want the corresponding one updated. How can I achieve this? Is this the correct way to pass information between two sibling directives confined inside a parent isolated scope?
Upvotes: 0
Views: 189
Reputation: 3010
Every isolate scope is child of the same $rootScope
so you cannot use the events to separate directives. $broadcast
-ed events are used for global (up to the root) communication.
To communicate directly with directives you can use the require
property of directives, so rpNavItem
can require rpNav
and use rpNav
to share state.
rpFlyout
is not needed for this example, javascript:
angular.module('app', ['rpNav']);
angular.module('rpNav', [])
.directive('rpNav', function() {
return {
scope: true,
controller: ['$scope', function ($scope) {
this.setSelectedCat = function (cat) {
$scope.category = cat;
}
}]
};
});
angular.module('rpNav')
.directive('rpNavItem', function() {
return {
restrict: 'E',
scope: {
cat: '@'
},
template: function (el, attrs) {
return '<div>Item ' + attrs.cat + '</div>';
},
require: '^rpNav',
link: function (scope, el, attrs, rpNav) {
el.on('click', function(){
scope.$apply(function () {
rpNav.setSelectedCat(scope.cat);
});
});
}
};
});
The HTML can become something like:
<div rp-nav>
<rp-nav-item cat="1"></rp-nav-item>
<rp-nav-item cat="2"></rp-nav-item>
<rp-nav-item cat="3"></rp-nav-item>
<p style="background-color: lightblue">{{category}}</p>
</div>
<hr>
<div rp-nav>
<rp-nav-item cat="one"></rp-nav-item>
<rp-nav-item cat="two"></rp-nav-item>
<rp-nav-item cat="three"></rp-nav-item>
<p style="background-color: lightblue">{{category}}</p>
</div>
If you wish to keep rpFlyout
directive for some reason you can make it have isolated storage too and pass the current category in an attribute (untested code):
<rp-flyout category="category"></rp-flyout>
Directive:
[...]
.directive('rpFlyout', function() {
return {
scope: {
'category': '='
},
template: '<p style="background-color: lightblue">{{category}}</p>'
};
});
Upvotes: 1