2

I've just started learning AngularJS and D3.js to plot the bar graph. I was success to plot one bar graph in a page. But I'm having a problem to plot more than one graph with different data. For ex: my app.js looks as follows:

// Module name to be included in html app
var app = angular.module('App', []);

// FundamoCtrl controller which holds the data from the JSON
app.controller("FundamoCtrl", function($scope) {

    $scope.tags = [
      {'#text': "author-vimal",    '@pass':  4},
      {'#text': "author-raj",      '@pass':  8},
      {'#text': "tt-positive",     '@pass': 15},
      {'#text': "tt-negative",     '@pass': 16},
      {'#text': "author-selvam",   '@pass': 23},
      {'#text': "author-inba",     '@pass': 42}
    ];

});

// Custom filter for the json data
app.filter('filterData', function() {

    return function(data, searchFor) {
        var property = Object.keys(searchFor)[0];
        var result = [];

        for (var i = 0; i < data.length; i++) {
            if (data[i][property].indexOf(searchFor[property]) > -1) {
                result.push(data[i]);
            }
        }

        return result;
    };

});

// Bar Graph to show the result
app.directive('barGraph', [
    '$filter',
    function($filter) {
        return {
            restrict: 'EA',
            scope: {
                data: '=',
                filtername: '=',
                filtervalue: '=',
            },
            link: function(scope, element, attrs) {
                var margin = {top: 20, right: 30, bottom: 30, left: 40}, 
                    width = 500 - margin.left - margin.right,
                    height = 300 - margin.top - margin.bottom;

                var x = d3.scale.ordinal()
                                .rangeRoundBands([0, width], .1);
                var y = d3.scale.linear()
                                .range([height, 0]);

                var xAxis = d3.svg.axis()
                                .scale(x)
                                .orient("bottom");
                var yAxis = d3.svg.axis()
                                .scale(y)
                                .orient("left")
                                .ticks(5);

                var svg = d3.select(element[0])
                                .append("svg")
                                .attr("class", "chart");

                scope.render = function(data) {

                    x.domain(data.map(function(d) { return d['#text']; }));
                    y.domain([0, d3.max(data, function(d) { return d['@pass']; })]);

                    var chart = d3.select(".chart")
                                .attr("width", width + margin.left + margin.right)
                                .attr("height", height + margin.top + margin.bottom)
                                .append("g")
                                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

                    var bar = chart.selectAll("g")
                                .data(data)
                                .enter()
                                .append("g")
                                .attr("transform", function(d, i) { return "translate(" + x(d['#text']) + ", 0)"; });

                    bar.append("rect")
                        .attr("class", "rect-bar")
                        .attr("y", function(d) { return y(d['@pass']); })
                        .attr("height", function(d) { return height - y(d['@pass']); })
                        .attr("width", x.rangeBand());

                    bar.append("text")
                        .attr("x", x.rangeBand() / 2)
                        .attr("y", function(d) { return y(d['@pass']) + 15; })
                        .attr("dy", ".5em")
                        .text(function(d) { return d['@pass']; })
                        .attr("class", "bar-text");

                    chart.append("g")
                        .attr("class", "x axis")
                        .attr("transform", "translate(0," + height + ")")
                        .call(xAxis);

                    chart.append("g")
                        .attr("class", "y axis")
                        .call(yAxis)
                        .append("text")
                        .attr("transform", "rotate(-90)")
                        .attr("y", 0 - margin.left)
                        .attr("x", 0 - (height / 2))
                        .attr("dy", "1em")
                        .style("text-anchor", "middle")
                        .text("Pass Count");
                };

                scope.$watch('data', function(data) {
                    data = $filter(scope.filtername)(data, scope.filtervalue);
                    scope.render(data);
            }, true);
            }
        };
    }
]);

And in my html template under body section, I've as follows:

<div ng-controller="MyCtrl">
    <bar-graph id="bar1" data="tags" filtername="'filterData'" filterValue="{'#text': 'author-'}"></bar-graph>

    <bar-graph id="bar2" data="tags" filtername="'filterData'" filterValue="{'#text': 'tt-'}"></bar-graph>
</div>

In output, the bar2 is scattered on top of the bar1. I would like to place bar2 next to bar1 which I'm unable to do. Kindly help me to solve this problem.

For more information, see this Plunker

1 Answer 1

2

Okay, so I found out the problem where it is. I am appending g tag to class attribute where the class value is chart. So it takes the first chart and appends to the same chart again and again. So the mess is.

Now I am creating a dynamic id which will be appended to the svg element at runtime which solves the above problem.

For more information, see Plunker.

Sign up to request clarification or add additional context in comments.

2 Comments

Generally it's a good idea to never do a d3.select() within a directive because this breaks out of the directive's encapsulation. Always start out with d3.select(element[0]) and then chain further selections on that. At least, that's my approach.
@EthanJewett: I have the same problem and arrived at the same conclusion as the OP. I would like to try out your approach. Do you have it documented or have an article that discusses your approach?

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.