Skip to Content
Author's profile photo Jeroen van der A

a new SDK bar chart

Some time ago I already made some bar charts, but now I wanted to expand it to more or less a complete version. Something one could imagine using in an actual dashboard.

With the help of the new SDK examples, the very insightful blogs of Michael Howles and the d3 tutorials here at the d3 library site (www.d3js.com) I was able to expand the bar chart quite a bit.

In April I will be attending the SDK course in Walldorf, using these kind of little projects will help me get the most out of those sessions as these will give me some hands-on experience.

/wp-content/uploads/2014/03/screenshot_402917.jpg

As you can see the bar chart has a tooltip and a hover color. All these are set in a separate CSS file with classes that can be changed from the custom CSS file in the application. Above the bars the values are shown.

This chart will provide fake data using a random function when no datasource is assigned. I the chart is bound then it will show that data.

Finally when you click a bar you can collect the key, the tekst and the value with the methods clickedKey, clickedText and clickedValue.

Setting up a d3 chart

In the init of the SDK i’ve set up the main parts of the chart and assigned these parts to variables


this.init = function() {
             var container = this.$()[0];
             var width = that.$().outerWidth(true) - margin.left - margin.right;
             var height = that.$().outerHeight(true) - margin.top - margin.bottom;
        
             chart = d3.select(container).append("svg:svg").attr("width", "100%").attr("height", "100%")
              .append("g")
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
        
             xAxisGroup = chart.append("g").attr("class", "x axis");
             yAxisGroup = chart.append("g").attr("class", "y axis");
             yAxisGroupText = yAxisGroup.append("text");
             barsContainer = chart.append('g').attr("class", "barscontainer");
             toolBar = chart.append("g");  


In the afterupdate a function is called that will build the graph by changing the variables that were initialised at the .init. Note that when you add elements in the afterupdate event, after each update a new element will be added to your graph.


this.afterUpdate = function() {
             drawVerticalBarChart();
       };


In the function the first check is to look if there is data present. If no data is bound to the chart then we will generate our own data.When we get data from the datasource we need to translate the json variable to our own json variable that fits the purpose of building the graph.


if(d3_data && d3_data.data) {
                    var values = d3_data.data.filter(isNotResult);
                    var names = d3_metadata.dimensions[1].members.filter(
                                        function (row){     if ("RESULT" === row.type) {return false;} else {return true;}});
               
                    dataset.length = 0;
                    for (var i=0,len=values.length; i<len; i++)
                    {
                           newjson = {};
                           newjson.key = names[i].key;
                           newjson.name =  names[i].text;
                           newjson.value = values[i];
                           dataset.push(newjson);
                    }
             }
             else {
                    var values = [],
                 i = 0;
                    end = Math.round(Math.random()*12) + 1;
             for(i=0; i<randomBars; i++){
                 values.push(Math.round(Math.random()*100));
             }    
             dataset.length = 0;
             for (var i=0,len=values.length; i<len; i++)
             {
                    newjson = {};
                    newjson.key = "la"+i;
                    newjson.name =  "la-" + (i + 1);
                    newjson.value = values[i];
                    dataset.push(newjson);
             }


Building the chart I heavily relied on the d3 tutorials and most of all this one : http://bost.ocks.org/mike/bar/3/

I added some transitions so the bars would make a transition fade with each change


                .transition()
                    .delay(function (d,i){ return i * 50;})
                    .duration(750)
                    .ease("elastic")
                    .style("opacity", 1);


With d3 you also can add onclick functions on every element. I added this to every bar


                .on("click", function(d, i) {
                  
                       clickedKey = d.key;
           
                       that.firePropertiesChanged(["clickedkey"]);


building these when you don’t have the experience is stumbling from obstacle to obstacle. But once you’ve completed one you have the ability to build all kinds of visualizations that meet specific needs and cannot be done with standard component.

Assigned Tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Mustafa Bensan
      Mustafa Bensan

      Hi Jeroen,

      Thanks for the post.  I'm curious to know the chart re-sizing behaviour with this example.  Specifically:

      1)  Does the chart automatically re-size/re-render on the canvas when the user changes the height or width by dragging the border handles or manually updating these properties in the properties panel?

      2)  If the height and width properties are set to auto and the margins to say zero, when viewed in the browser does the chart automatically re-size when the user changes the size of the browser window?

      My understanding is that it can be a little tricky to build in auto re-sizing with D3 so I was interested to know how your component behaves.

      Regards,

      Mustafa. 

      Author's profile photo Jeroen van der A
      Jeroen van der A
      Blog Post Author

      hi Mustafa,

      it does resize on the canvas, but doesn't in the browser when resizing with the auto settings on height / width.

      to be honest i checked that now for the first time after your question.

      Jeroen