TomNeyland / angular-dc

AngularJS directives for dc.js
http://tomneyland.github.io/angular-dc/
MIT License
112 stars 59 forks source link

Enable dc-chart-group Parameter For dc-select directive #44

Open nsubordin81 opened 9 years ago

nsubordin81 commented 9 years ago

First of all let me complement you on this excellent work you have done wrapping dc.js for use with angular, it was a lifesaver for me. I thought you might be pleased to know that it was fairly seamless for me to use angular-dc with blairn's sunburst chart pull request that isn't even fully merged into masterAPI for dc-js yet dc-js/dc.js#907

Something I was having trouble with was I needed a dropdown to filter all of my charts and so I was happy to find reading through your src that you already had written something to support this. What I didn't realize was that I had specified a chart group of "1" for all of my charts, much like in the Nasdaq example. This being the case, when I used my dc-select dropdown the crossfilter dimensions would update but then the bound chart directives weren't updating until I filtered using one of the other charts.

after a little bit of headscratching, I realized my error was in not adding the dcChartGroup, but looking at the 'dcSelect' code it doesn't seem to support having a chart group as an attribute. I wrote a local fix for it but I don't know if it breaks the default case or has other vulnerabilities to it. Also, following your pattern from dcChart I used iAttrs parameter but since I had to reference it in the callback I am accessing it directly to pass in the argurment to dc.redraw() which feels messy. Here is the modification as I have it (I marked where I modified things with double asterisk comments):

/* Another directive, responsible of integration angular's select directive with dc.

    <dc-select dc-dimension="fooDimension", all-label="All foos"/>

   This directive helps to filter by arbitrary dimensions without need for another graph.

   Note that if there is a graph on the same dimension as the select, changing the select value
   will not update the graph's own selection. This is also the case if you make 2 graphs
   with same dimension. This is a limitation of the underlying lib dc.js
*/

angularDc.directive('dcSelect', [
    function() {
        return {
            restrict: 'E',
            scope: {
                dcDimension: '=',
                allLabel: '@'
            },
            template: '<select class="form-control" ng-model="selectModel" ' + 'ng-options="d.key for d in selectOptions">',
            link: function(scope, iElement, iAttrs) {
                scope.$watch('dcDimension', function(dimension) {
                    /**adding chartGroup parameter here**/
                    var allkeys, chart
                    , chartGroupName = iAttrs.dcChartGroup;
                    if (dimension !== null) {
                        // we make a fake chart so that the dimension is known by dc.filterAll()
                        chart = dc.baseMixin({});
                        chart.dimension(dimension);
                        chart.group(dimension);
                        /**need to add chart to group here and use same param as other directives for chart groups
                        to have selections update other charts in the same group. **/
                        dc.registerChart(chart, chartGroupName)
                        chart._doRender = function() {};
                        chart._doRedraw = function() {};
                        scope.selectModel = {
                            key: scope.allLabel
                        };
                        allkeys = dimension.group().orderNatural().all();
                        scope.selectOptions = [scope.selectModel].concat(allkeys);
                    }
                });
                return scope.$watch('selectModel', function(sel) {
                    if (scope.dcDimension !== null) {
                        if (sel !== null && sel.key !== scope.allLabel) {
                            scope.dcDimension.filter(function(d) {
                                return d === sel.key;
                            });
                        } else {
                            scope.dcDimension.filter(null);
                        }
                        /** Have to pass the chartGroup to dc's redraw function or it will use the default chartGroup**/
                        dc.redrawAll(iAttrs.dcChartGroup);
                    }
                });
            }
        };
    }
]);

Thanks again for publishing this repo and maintaining it. Keep up the good work!

Taylor