MBehtemam
MBehtemam

Reputation: 7919

Dynamically Create and Load Angular Directive

In my application i have a list of custom directive names.

$scope.data =["app-hello","app-goodby","app-goodafter"];

each name in this array is one directive that im created.

var app = angular.module('app',[]).controller('mainCtrl',function($scope){
 $scope.data =["app-hello","app-goodby","app-goodafter"];
}).directive('appHello',function(){
 return {
  restrict:'EA',
  template:'<h1>Hello Directive</h1>'
};
}).directive('appGoodbye',function(){
return {
 restrict:'EA',
template:'<h1>GoodBye</h1>'
 };
}).directive('appGoodafter',function(){
  return{
restrict:'EA',
template:'<h1>Good Afternoon</h1>'
};
});

now i want to load directive with ng-repeat in the view for example because i used EA restrict for directive can create directive in ng-repeat like this :

<div ng-repeat="d in data" >
  <div {{d}}></div>
</div>

but this way it doesn't work. so the real question is if i have list of directive how to load this directive with ng-repeat.for this scenario i create a jsbin . thanks.

Upvotes: 1

Views: 206

Answers (3)

SamMorrowDrums
SamMorrowDrums

Reputation: 572

I actually prefer to create templates, that just contain the directive. Then you can use ng-include this then enables you to easily pass scope variables into the dynamically chosen directives too.

Here is my widget code fore example:

<div ng-repeat="widget in widgets track by $index" ng-include="widget.url" class="widget-container" ng-class="widget.widget_type.config.height +' ' + widget.widget_type.config.width">
</div>

Then I set the widget.url to a template containing just the right directive.

I can then in my directive do this:

<custom-widget ng-attr-widget="widget"></custom-widget>

Then I have access to the dynamic variable too, so I can access configuration specifics too, without having to dynamically generate HTML strings and compile them. Not a perfect solution, but personally I used to use the other approach mentioned, and discovered that this fit my needs much better.

Upvotes: 0

akn
akn

Reputation: 3722

You can do it in this way:

Directive:

app.directive('compile',function($compile){
  return{
    restrict:'A',
    template: '<div></div>',
    link:function(scope,elem,attrs){
      scope.name = attrs.compile;
      elem.children('div').attr(scope.name,'');
      $compile(elem.contents())(scope);
    }
  };
});

HTML:

  <div ng-repeat="d in data" compile="{{d}}">
  </div>

Jsbin: http://jsbin.com/wofituye/4/edit

Upvotes: 1

gkalpak
gkalpak

Reputation: 48212

You need a "master" directive that $compiles the HTML (optionally containing directives) into an Angular-aware template and then links the compiled element to a $scope:

app.directive('master', function ($compile) {
    return {
        restrict: 'A',
        link: function postLink(scope, elem, attrs) {
            attrs.$observe('directive', function (dirName) {
                if (dirName) {
                    var compiledAndLinkedElem =
                            $compile('<div ' + dirName + '></div>')(scope);
                    elem.html('').append(compiledAndLinkedElem);
                }
            });
        }
    };
});

<div master directive="{{dir}}" ng-repeat="dir in ['dir1', 'dir2', 'dir3']"></div>

See, also, this short demo.

Upvotes: 2

Related Questions