When you need to exchange data between two custom directives without using a service, the ngModel directive can be used create a communication channel. Using this built in Directive you can pass data between custom directives as this example illustrates. For this technique to work certain conditions must be met:
1/ The directives must be enclosed within the same parent controller
2/ The custom directive attributes must be assigned to the same variable name
In the code sample on Plunker, we have two Phone Networks, Verizon and Sprint, representing the two custom directives. The phone type represents the data to be passed between the directives. The directives are named sprint-network
and verizon-network
and the parent controller is netController
. The two directives are defined in the sprintModule.js file and they have separate template files: templatesprint.html and templateverizon.html.
netController
is the parent controller which wraps the two directives within a common parent scope. And the samsung
attribute in sprintNetwork directive is assigned to the phone
scope variable. In the verizonNetwork directive, the iphone
attribute gets assigned to the similar phone
scope variable. These two scope variables belong to separate isolated scopes and would normally have different values. However using the ngModel
directive through the require
method in the verizonNetwork
directive, the two variables are data bound. Placing the ^
character before ngModel
makes the ngModel
a required attribute in the verizonNetwork
directive when it’s implemented in the index.html
file. Using ?
makes the attribute optional. Note that the link
method in verizonNetwork
directive takes ngModel
as the fourth argument. To illustrate this technique, change the phone brand from the drop down in verizonNetwork
(and click the “get phone” button) to update the phone
scope variable in both directives.
var networkTwoApp = angular.module("networkApp", []); networkTwoApp.controller("netController", function ($scope){ $scope.phone = "Apple iPhone 5"; }); networkTwoApp.directive("sprintNetwork", function() { console.log("networkTwo"); return { restrict: 'AE', scope:{ samsung: "=", }, templateUrl: "templatesprint.html", link: function(scope, element, attrs, ngModel) { ngModel.$setViewValue(scope.phone); ngModel.$viewChangeListeners.push(function(){ console.log("sprint view change"); }); } }; }); networkTwoApp.directive("verizonNetwork", function () { return{ restrict: 'AE', scope:{ iphone: "=", }, templateUrl: "templateverizon.html", require: '^ngModel', link: function (scope, element, attrs, ngModel) { scope.phone = "my phone"; ngModel.$setViewValue(scope.phone); scope.showPhone = function(){ ngModel.$setViewValue("setviewvalue"); ngModel.$setViewValue(scope.phone); console.log("clicked"); }; scope.phonedata = "my phone is cool"; } } });
Leave a Reply