0

I am working on an Angular 1 app and I need to call different directives based on a value in a ng-repeat loop. I am using ng-if so far which renders that directive if it matches the condition but what I am thinking is that if I got 100 directives after some time, then I will be using 100 ng-ifs and I am thinking there must be some better solution for this.

Here's some of my code

Template which calls the directive

<render-directive ng-if="data.length !== 0" data="data"></render-directive>

Template of renderDirective

<div ng-repeat="element in data">
  <div ng-if="element.item === 'motor'">
    <render-motor motor-id="element.id" name="element.item"
              checked="element.params.switch"></render-motor>
  </div>

  <div ng-if="element.item === 'adc'">
    <render-adc adc-id="element.id" name="element.item"></render-adc>
  </div>
</div>

For sake of simplicity, I've only shown two directives but in real I am already calling more than 10 directives and it can go upto 100 in future.

So does anyone can tell me a better way to do this, where I won't have to use ng-if for every directive?

Please do let me know if I haven't cleared something in question.

UPDTAE

For clearing what I am exactly looking for, I have an array which has 'item' propery and according to that property I want to call a directive. So for eg,

  • for item = "motor", I want to call motorDirective
  • for item = "switch", I want to call switchDirective
  • for item = "led", I want to call ledDirective

and so on.

4
  • What you exactly need? do loop different data with different structure or data with different template ? Commented Jan 2, 2017 at 13:02
  • Please see the update Commented Jan 2, 2017 at 13:18
  • Look into using the ng-switch directive. It has less overhead than using several ng-if directives. Commented Jan 2, 2017 at 21:13
  • @myke_11j please check my updated answer, it should be better now. Commented Jan 3, 2017 at 17:22

2 Answers 2

1

I had to update my answer as it was tricky to pass a scope to ng-bind-html.

Moreover a solution with a polymorphic directive is way nicer as it also save the declarative part of a table driven solution.

The final solution where the interesting part is the polymorph directive:

var app = angular.module('app',[]);

app.controller('elementsCtrl',['$scope', function($scope){
  
  $scope.elements = [
    {type: 'motor'},
    {type: 'adb'},
    {type: 'led'},
    {type: 'motor'}
  ];
}]);

app.directive('polymorph', ['$compile', function($compile){
  return{
    restrict: 'E',
    scope: {
      type: '@',
      item: '='
    },
    link: function(scope, element, attr){
      var result = $compile('<div '+ scope.item.type +'></div>')(scope);
      element.append(result);
    }
  }
}]);

app.directive('motor', function(){
  return{
    restrict: 'A',
    replace: true,
    template: '<div style="color:blue;">{{item.type}}</div>'
  }
});


app.directive('led', function(){
  return{
    restrict: 'A',
    replace: true,
    template: '<span style="color:green;">{{item.type}}</span>'
  }
});

app.directive('adb', function(){
  return{
    restrict: 'A',
    replace: true,
    template: '<p style="color:red;">{{item.type}}</p>'
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>


<div ng-app="app" ng-controller="elementsCtrl">
  <div ng-repeat="element in elements">
    <polymorph type="{{element.type}}" item="element"></polymorph>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

this might do it for me...I will try this. Thanks
Yes I needed something like this. $compile was the solution for me. Thanks Piou
1

You need to use $compile in the renderDirective .

In the compile step , we need to compile the dynamically required directive .

1 Comment

Can you post a snippet of how I can use compile block in a directive to call different directives? Thanks

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.