Abhirath Mahipal Abhirath Mahipal - 1 year ago 67
JSON Question

Optimal way to use Angular Directives and JSON

I want an efficient way to factor an Angular Directive that is written to display a chart.

After reading other answers here, I found a nice way to create a directive that displays a single chart without any problem.

How do I reuse the same directive to display different charts? Each chart needs a JSON object that has settings and data in order to render.

I don't want to pollute my Angular View by typing 100-150 lines of JSON and passing it in via the directive.

Details:-


  • Each chart has some common key/value pairs that I can leave in the directive.

  • How do I infuse chart specific key & value pairs in each directive?



Eg:- Say I want one chart to have green bars and the other chart to have red lines.

Angular Directive

(function () {

'use strict';

angular
.module("analytics")
.directive("angularDirectiveAmcharts", angularDirectiveAmcharts);

function angularDirectiveAmcharts() {

var directive = {
link: link,
restrict: 'A',
replace: true,
scope: {
chartdata: '=',
type: '=',
customstyle: '@',
chartsettings: '=',
chartid: '@'
},
template: '<div id="{{ chartid }}" style="{{ customstyle }}"></div>'
};

return directive;


function link(scope, elem, attrs) {
AmCharts.makeChart(scope.chartid, {
"type": "serial",
"categoryField": "date",
"autoMarginOffset": 10,
"marginRight": 20,
"marginTop": 20,

//I've deleted lots of keys and values for the sake of brevity


"dataProvider": scope.chartdata
});


}
}
})();


View

<div class="chartarea" ng-controller="pcController as vm">

<div angular-directive-amcharts chartid="chartdiv" chartdata="vm.chart_data"></div>

</div>


I am particular about maintainability because a lot of changes are going to made after I'm done with my internship.

Answer Source

Parts of the given code in this answer are based on another answer

You could use a service to provide a standard configuration to all of your chart directives. In this service you can define this standard configuration once and merge it with a specific configuration each time, a directive is created. This way you only have to declare minor changes in your controller.

Nonrequired but possible config binding into directive:

<div ng-controller="myCtrl">
    <my-chart></my-chart>
    <my-chart config="conf"></my-chart>
</div>

Specific configuration in controller:

myapp.controller('myCtrl', function ($scope) {
    $scope.conf = {
        graphs: [{ type: 'column' }]
    };
});

Service for default configuration (using jQuerys way to deep merge objects):

myapp.service('chartService', function () {
    this.defaultConfig = {
        "type": "serial",
        // reduced object for readabilty
    };
    this.getConfig = function (mergeObj) {
        return $.extend(true, {}, this.defaultConfig, mergeObj);
    }
});

The data is get through another service, and added to the configuration after the merge:

var config = chartService.getConfig(scope.config || {});
config.dataProvider = dataProvider.getData();
chart = AmCharts.makeChart(element[0], config);

I've prepared a fiddle, so you can take a look into an example.