3
\$\begingroup\$

I have a nested JSON of multiple levels. The last level has the "series data" that is to be added to the highcharts options to render the chart data of interest.

I am sniffing the JSON and populating the options in each level which is set as a watched model in the controller and modifying the chart data, which is watched inside of the directive and chart updated on the change of these models.

I am looking to structure this as a reusable component and wondering on the best practice to do so. Seems to me, the "JSON selection" part and the "chart rendering" part can be best as their own directives that communicate amongst each other.

Do you concur or suggest an alternative approach?

Controller:

app.controller('MyCtrl',function($scope,Data,ForwardChart){
    http.get('scripts/lib/bds2.json').success(function(api_data){
        $scope.r_api_data = api_data.res;

        var available_options = [];
        var chosen_options= [];
        var current_json = $scope.r_api_data;
        for (var i=0; i<2; i++){
            var json_options = _.keys(current_json);
            available_options.push(json_options);
            chosen_options.push(json_options[0]);

            current_json = current_json[json_options[0]];
        }

        $scope.plot_data = function(){
            var bdfs_chart = {
                series : Data.get_serieses($scope.r_api_data,$scope.chosen_options)
            };
            $scope.bdfs_chart = $.extend(true,angular.copy(ForwardChart),bdfs_chart);
        };

        $scope.chosen_options = [];
        $scope.available_options = available_options;

        $scope.$watch('chosen_options', function(){
            $scope.plot_data();
        },true);

        $scope.chosen_options = chosen_options;
    })
});

Directive:

app.directive('intchart', function(){
    return {
        restrict: 'E',
        template: '<div class="hc-bars"></div>',
        scope: {
            chartData: "=chartId"
        },

        link: function(scope, element, attrs){
            var chartsDefaults = {
                chart: {
                    renderTo: element[0],
                    type: attrs.type || null,
                    height: attrs.height,
                    width: attrs.width
                },
                colors: attrs.color.split(",")
            };
            var chart = {};
            scope.$watch(function() { return scope.chartData; }, function(value){
                var chart_json = {};
                if (chart.hasOwnProperty('series') && chart.series.length>0){
                    for (var i = 0; i < value.series.length; i++) {
                        chart.series[i].setData(value.series[i].data);
                    }
                } else{
                    $.extend(true, chart_json, chartsDefaults, value);
                    chart = new Highcharts.Chart(chart_json);
                }
            }, true);
        }
    }
})
\$\endgroup\$
2
  • \$\begingroup\$ btw, instead of function() { return scope.chartData; } as a watcher target, it is valid to just put the string "chartData", and of course easier to read. \$\endgroup\$
    – Nat
    Commented Jan 31, 2014 at 9:29
  • \$\begingroup\$ Also if I understand correctly what is meant to happen in the controller, It looks like you're relying on the ordering of object keys to get chosen_options from the current_json object, this might usually work but is not guaranteed to. stackoverflow.com/questions/5525795/… \$\endgroup\$
    – Nat
    Commented Jan 31, 2014 at 9:49

1 Answer 1

1
\$\begingroup\$

It's difficult to tell from these snippets exactly what you're trying to achieve, but I think the questions you have to ask are; how do you anticipate reusing this code? If reusability is the feature, what are the use cases?

If you anticipate needing multiple distinct controllers with a significant and coherent subset of the logic in the get request in the controller, the consider extracting it into a service, to save logic duplication.

Alternatively, if the contents of the controller are only needed for the directive, consider making the controller part of the directive, rather than requiring them to be correctly used in conjunction.

The directive looks good from what I can tell.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.