Talk is cheap, show my codes first:
HTML:
<div add-icons="IconsCtrl"> </div>
directive:
angular.module('attrDirective',[]).directive('addIcons', function($compile){ return { restrict : 'A', controller : "IconsCtrl" }, link : function (scope, elem , attrs, ctrl) { var parentElem = $(elem); var icons = $compile("<i class='icon-plus' ng-click='add()'></i>)(scope); parentElem.find(".accordion-heading").append(icons); }, }
});
controller:
function IconsCtrl($scope){ $scope.add = function(){ console.log("add"); }; }
now it works, when i click the plus icon, browser console output "add".
but i want to set the controller into the directive dynamically,like this:
HTML:
<div add-icons="IconsOneCtrl"> </div> <div add-icons="IconsTwoCtrl"> </div>
Controller:
function IconsOneCtrl($scope){ $scope.add = function(){ console.log("IconsOne add"); }; } function IconsTwoCtrl($scope){ $scope.add = function(){ console.log("IconsTwo add"); } }
directive likes :
angular.module('attrDirective',[]).directive('addIcons', function($compile){ return { restrict : 'A', controller : dynamic set,depends on attrs.addIcons }, link : function (scope, elem , attrs, ctrl) { var parentElem = $(elem); var icons = $compile("<i class='icon-plus' ng-click='add()'></i>)(scope); parentElem.find(".accordion-heading").append(icons); }, } });
how to achieve my goal? thanks for your answer!
You just create a myVar variable in your controller and pass it to the directive using my-var attribute. Since you are using two way binding, any changes made to myVar by the directive are available in your controller.
AngularJS ng-controller Directive The ng-controller directive adds a controller to your application. In the controller you can write code, and make functions and variables, which will be parts of an object, available inside the current HTML element. In AngularJS this object is called a scope.
Answer:The link option is just a shortcut to setting up a post-link function. controller: The directive controller can be passed to another directive linking/compiling phase. It can be injected into other directices as a mean to use in inter-directive communication.
Now it is possible with AngularJS. In directive you just add two new property called controller
, name
property and also isolate scope
is exactly needed here.
Important to note in directive
scope:{}, //isolate scope controller : "@", // @ symbol name:"controllerName", // controller names property points to controller.
Working Demo for Setting Dynamic controller for Directives
HTML Markup :
<communicator controller-name="PhoneCtrl" ></communicator> <communicator controller-name="LandlineCtrl" ></communicator>
Angular Controller and Directive :
var app = angular.module('myApp',[]). directive('communicator', function(){ return { restrict : 'E', scope:{}, controller : "@", name:"controllerName", template:"<input type='text' ng-model='message'/><input type='button' value='Send Message' ng-click='sendMsg()'><br/>" } }). controller("PhoneCtrl",function($scope){ $scope.sendMsg = function(){ alert( $scope.message + " : sending message via Phone Ctrl"); } }). controller("LandlineCtrl",function($scope){ $scope.sendMsg = function(){ alert( $scope.message + " : sending message via Land Line Ctrl "); } })
Your case you can try this below code snippets.
Working Demo
HTML Markup :
<div add-icons controller-name="IconsOneCtrl"> </div> <div add-icons controller-name="IconsTwoCtrl"> </div>
Angular Code :
angular.module('myApp',[]). directive('addIcons', function(){ return { restrict : 'A', scope:{}, controller : "@", name:"controllerName", template:'<input type="button" value="(+) plus" ng-click="add()">' } }). controller("IconsOneCtrl",function($scope){ $scope.add = function(){ alert("IconsOne add "); } }). controller("IconsTwoCtrl",function($scope){ $scope.add = function(){ alert("IconsTwo add "); } });
This is how it is done:
Inside your directive element all you need is an attribute which gives you access to the name of the controller: in my case my card attribute holds a card object which has a name property. In the directive you set the isolate scope to:
scope: { card: '=' }
This isolates and interpolates the card object to the directive scope. You then set the directive template to:
template: ''
,
this looks to the directive's controller for a function named getTemplateUrl
and allows you to set the templateUrl
dynamically as well. In the directive controller the getTemplateUrl
function looks like this:
controller: ['$scope', '$attrs', function ($scope, $attrs) { $scope.getTemplateUrl = function () { return '/View/Card?cardName=' + $scope.card.name; }; }],
I have an mvc controller which links up the proper .cshtml file and handles security when this route is hit, but this would work with a regular angular route as well. In the .cshtml/html file you set up your dynamic controller by simply putting as the root element. The controller will differ for each template. This creates a hierarchy of controllers which allows you to apply additional logic to all cards in general, and then specific logic to each individual card. I still have to figure out how I'm going to handle my services but this approach allows you to create a dynamic templateUrl and dynamic controller for a directive using an ng-repeat based on the controller name alone. It is a very clean way of accomplishing this functionality and it is all self-contained.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With