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
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>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With