Question

I have been assigned the task of creating a set of "cards" like on Google one and other similar sites using AngularJS for a dashboard. Each card has independent functionality from the rest and they all must appear as soon as their data has been returned from the API. In the future we are going to allow for the pinning/unpinning of these cards to the dashboard, as well as ordering to be customized by the user.

I have created a "card-dealer" directive that will contain an ng-repeat for each card in an array of card objects. Each of these cards needs to have their own dynamic template and controller, which is where I have ran into an issue. I was able to figure out how to pass in a dynamic templateUrl, but the controller is a different story. I have all but got it figured out by mimicking what I watched on a Pluralsight video, I should just be able to pass a card.controller variable into the directive "ctrl" attribute like this:

<card-dealer ng-repeat="card in cards" card="card" ctrl="{{card.controller}}"/>

However, the ctrl='{{card.controller}}' variable in the directive is not being parsed before it is sent to the directive. In the directive I set the controller dynamically by setting controller: '@' and name: 'ctrl'. This looks into the element for the attribute named "ctrl" and returns it's value as the name of the controller. This method works when I type in the string name of the directive controller instead of using the {{card.controller}} variable, but simply typing a string isn't dynamic.

I need the variable to be parsed before it reaches the directive so that it looks for the proper controller name. I have created a JS Fiddle to demonstrate my issue: http://jsfiddle.net/kPdCk/. This should return two alert boxes, one representing each directive controller. If you run this currently, you'll see in the console log that it is trying to search for a controller with the name of the variable instead of the value of the variable.

Please help!! This is crucial to the future of our entire dashboard, once we figure out how to pass in a dynamic controller name we will be golden. Thanks in advance!!!

Was it helpful?

Solution

This is how it is done:


Inside your directive all you need is an attribute which gives you access to the name of the card: <card-dealer ng-repeat="card in cards" card="card"> </card-dealer> 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: '<div ng-include="getTemplateUrl()"></div>', this looks to the directive's controller for a function named getTemplateUrl. This is what you want because the directive controller has access to the scope object. 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 file you set up your dynamic controller by simply putting <div ng-controller="CardContactController"></div> as the root element. The controller will differ for each card. 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 card name alone. It is a very clean way of accomplishing this functionality and it is all self-contained.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top