Reputation: 159
What is the preferred way to link/bind two directives together? I have a controller with two directives, first directive is a select element, after selecting option, second directive should process selected item value.
App code:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function() {
var sharedData = { selectedId: '' };
var vm = this;
vm.sharedData = sharedData;
});
app.directive('directiveA', ['$compile', function($compile) {
return {
restrict: 'E',
scope: {
selectedId: '='
},
template: '<select data-ng-model="vm.sharedData.selectedId" data-ng-options="currentSelect.Id as currentSelect.Name for currentSelect in vm.sharedData.availableSelects track by currentSelect.Id"><option value="">Select option</option></select><p>Directive A, selected ID: {{vm.sharedData.selectedId}}</p>',
bindToController: true,
controllerAs: 'vm',
controller: function() {
vm = this;
vm.sharedData = {
availableSelects: [
{Id:1, Name: 'Option 1'},
{Id:2, Name: 'Option 2'},
{Id:3, Name: 'Option 3'},
{Id:4, Name: 'Option 4'}
]
}
vm.logMessage = logMessage;
function logMessage(selectedId) {
console.log('directiveA: ' + selectedId);
}
},
link: function($scope, elem, attr, ctrl) {
attr.$observe('selectedId', function(selectedId) {
ctrl.logMessage(selectedId);
});
}
};
}]);
app.directive('directiveB', ['$compile', function($compile) {
return {
restrict: 'E',
scope: {
selectedId: '='
},
template: '<p>Directive B, selected ID: {{vm.sharedData.selectedId}}</p>',
bindToController: true,
controllerAs: 'vm',
controller: function() {
vm = this;
vm.logMessage = logMessage;
function logMessage(selectedId) {
console.log('directiveB: ' + selectedId);
}
},
link: function($scope, elem, attr, ctrl) {
attr.$observe('selectedId', function(selectedId) {
ctrl.logMessage(selectedId);
});
}
};
}]);
HTML code:
<!DOCTYPE html>
<html data-ng-app="plunker" data-ng-strict-di>
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link href="style.css" rel="stylesheet" />
<script data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js" data-require="[email protected]"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl as vm">
<p>MainCtrl, selected ID: {{vm.sharedData.selectedId}}</p>
<directive-a data-selected-id="vm.sharedData.selectedId"></directive-a>
<directive-b data-selected-id="vm.sharedData.selectedId"></directive-b>
</body>
</html>
Here is a Plunker example:
http://plnkr.co/edit/KVMGb8uAjUwD9eOsv72z?p=preview
What I'm doing wrong?
Best Regards,
Upvotes: 2
Views: 2151
Reputation: 1010
The key issue revolves around your use of isolated scopes:
scope: {
selectedId: '='
},
With controllerAs binding:
controllerAs: 'vm',
What this essentially does, to put it basically, is it places the view model onto the directives scope, accessed through the alias you assign in the controllerAs. So basically in your html when you go:
<directive-a data-selected-id="vm.sharedData.selectedId"></directive-a>
You are actually accessing the directive-a view model, NOT the MainCtrl view model. BECAUSE you set directive-a as having an isolate scope... which is a new scope, isolated from the MainCtrl.
What you need to do is more along the following lines:
http://plnkr.co/edit/wU709MPdqn5m2fF8gX23?p=preview
EDIT
TLDR: I would recommend having unique view model aliases (controllerAs) when working with isolated scopes to properly reflect the fact that they are not the same view model.
Upvotes: 1