Display a directive inside another directive (in the repeater template)

I am trying to make a directive inside another directive (not sure if the repeater works inside the template), and it seems that it simply displays as text, and does not compile the directive (here plunker code: http://plnkr.co/edit/IRsNK9 )

Any ideas on how I can get it to correctly display the directives my-dir-one, my-dir-two, my-dir-three inside the repeater?

index.html

<!doctype html> <html ng-app="plunker" > <head> <meta charset="utf-8"> <title>AngularJS Plunker</title> <link rel="stylesheet" href="style.css"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.js"></script> <script src="app.js"></script> <script id="partials/addressform.html" type="text/ng-template"> partial of type {{type}}<br> </script> </head> <body> <div container></div> <br /><br /><br /> <b>Below is just to test the directives are actually usable outside the repeater</b> <div my-dir-one></div> <div my-dir-two></div> <div my-dir-three></div> </body> </html> 

app.js

 var app = angular.module('plunker', []); app.directive('container', function () { return { restrict: 'A', scope: {}, replace: true, template: '<div class="views">' + ' <div class="view" ng-repeat="view in views">' + ' <div {{view.dir}}>{{view.dir}}</div>' + ' </div>' + '</div>', link: function (scope, elm) { scope.views = [ { dir: 'my-dir-one' }, { dir: 'my-dir-two' }, { dir: 'my-dir-three' } ]; } } }); app.directive('myDirOne', function () { return { restrict: 'A', scope: {}, replace: true, template: '<div>This is directive one.</div>' } }); app.directive('myDirTwo', function () { return { restrict: 'A', scope: {}, replace: true, template: '<div>This is directive two.</div>' } }); app.directive('myDirThree', function () { return { restrict: 'A', scope: {}, replace: true, template: '<div>This is directive three.</div>' } }); 
+7
source share
2 answers

I managed to get around this problem by rewriting the code:

First, I updated the template code as follows:

 template: '<div class="views">' + ' <div class="view-wrapper" ng-repeat="view in views">' + ' <div view="{{view.dir}}"></div>' + ' </div>' + '</div>', 

Please note that I created a new 'view' directive. The following definition of a view directive is as follows:

 app.directive('view', ['$compile', function (compile) { return { restrict: 'A', scope: { view: '@' }, replace: true, template: '<div class="view"></div>', controller: ['$scope', function (scope) { scope.$watch('view', function (value) { scope.buildView(value); }); }], link: function (scope, elm, attrs) { scope.buildView = function (viewName) { var view = compile('<div ' + viewName + '></div>')(scope); elm.append(view); } } } }]); 

Thus, the variable view.dir is passed as an attribute of the 'view' directive, which then tracks its value and compiles the template with the directive in it.

+8
source

This is partly a synchronization problem ... I think that by the time he resolved expressions {{}}, he already parsed and issued directives. This is not a nesting or repeater issue.

What you are here is to "decide which directive to render based on the value of the variable." There are several ways to do this.

Here is one that should work, although it may not scale as well as we would like:

 <div class='views' ng-repeat='view in views'> <div ng-switch='view.dir'> <div ng-when='my-dir-one' my-dir-one /> <div ng-when='my-dir-two' my-dir-two /> <div ng-when='my-dire-three' my-dir-three /> </div> </div> 

Other options for similar tricks: it looks like you could use ngBindTemplate to take a row from your data and use it as a template for an element. This would probably allow some kind of complex (and inaudible) behavior.

You can specify a directive for an element as a class, but I do not know if using ngClass can do this so that you can dynamically select the directive, or it will be too late in the pipeline.

0
source

All Articles