Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What pattern to use for different AngularJS directives in an ng-repeat based on dynamic data

I'm building a dashboard dynamically from an array of data. The gauges are D3.

I have a selection of different D3 gauges defined in AngularJS directives. On my page I have an ng-repeat iterating over the metrics array.

The question I have is what is the best way to dynamically select the right directive based on an attribute of data in the ng-repeat array?

Is there a way to create a factory pattern where the Directive used is based on an input value from the array? Or is there a way to achieve the result using only Directives by dynamically including other Directives in a Directive?

HTML

<div ng-controller="DashboardCtrl">
<div id="oppChart">
    <div>
        <gh-visualization ng-repeat="item in metrics" val="item[0]"></gh-visualization>
    </div>
</div>
</div>

Metrics array (will be dynamic):

$scope.list = [
        { 'title': 'XYX','data-type':'', 'query':'SELECT ...' },
        { 'title': 'Revenue', 'data-type':'', 'query':'SELECT ...'  }
      ];

D3 Directive based on this - http://briantford.com/blog/angular-d3.html

like image 208
wisemanIV Avatar asked Sep 06 '13 19:09

wisemanIV


2 Answers

That would be ng-switch

<div ng-repeat="item in metrics">
  <div ng-switch on="item.type">
    <div ng-switch-when="optionA">..include </div>
    <div ng-switch-when="optionA">..include </div>
  </div>
</div>
like image 66
Mike Robinson Avatar answered Sep 18 '22 11:09

Mike Robinson


Yup I've done this as you describe in your second option.

I created a directive that loads a particular template that then has other directives in them based on a type attribute of the data.

    directive("dynamicFormInput", ['$http', '$templateCache', function($http, $templateCache){
    return {
        restrict: 'E',
        //currently need model for map center otherwise can be removed, need to set default in map directive
        scope: {model: '=', section: '='},
        template: '<ng:include src="tpl"></ng:include>',
        link: function(scope, iElement, iAttrs) {
            var sectionToLoad = "";
            switch(scope.section.sectionTypeId)
            {
                case 1:
                    sectionToLoad ='partials/survey/textInput.html';
                  break;
                case 2:
                    sectionToLoad = 'partials/survey/selectOneOption.html';
                  break;
                case 3:
                    sectionToLoad = 'partials/survey/multiSelectOption.html';
                  break;
                case 4:
                    sectionToLoad = 'partials/survey/boolean.html';
                  break;
                case 5:
                    sectionToLoad = 'partials/survey/textInput.html';
                  break;
                case 6:
                    if(scope.section.sectionId == 13)
                        sectionToLoad = 'partials/survey/addressSelection.html';
                    else if(scope.section.sectionId == 24)
                        sectionToLoad = 'partials/survey/contactForm.html'
                break;
            }
            if(sectionToLoad!="")
            {
                $http.get(sectionToLoad, {cache:$templateCache});
                scope.tpl=sectionToLoad;
            }
        }
    }
}])

Usage is then like:

<accordion
    close-others="true">
    <accordion-group
        ng-repeat="section in sections"
        ng-class="{'isGroundTruthed':section.userId==73}"
        heading="{{section.sectionName}} ({{displaySelection(section)}})">

        <dynamic-form-input
            section="section">
        </dynamic-form-input>

    </accordion-group>
</accordion>

You can ignore the accordion I just happened to use that as my item to repeat so each section would fold up.

Edit Just cleaned up my directive code some.

like image 27
shaunhusain Avatar answered Sep 22 '22 11:09

shaunhusain