javascriptd3.jscognoscognos-10cognos-bi

IBM Cognos Analytics with D3.js Bar Chart height problem


I have problems configuring the D3 bar chart sample in IBM Cognos Analytics. I've edited the D3 sample from Cognos to incorporate titles for the values, but unfortunately I can't seem to get the data to display properly. It looks like the rectangles are properly assigned to the values, but the height of every bar is the same. Because of that it looks like 1 big bar.

Does anyone know how to fix that? I've tried looking at some examples on bl.ocks.org, but it just doesn't work (for example I tried copying this https://bl.ocks.org/caravinden/eb0e5a2b38c8815919290fa838c6b63b)!

This is how it looks:

enter image description here

define( ["https://censored/samples/javascript/lib/d3.min.js"], function( d3 ) {
"use strict";

function D3BarChart()
{
};

D3BarChart.prototype.draw = function( oControlHost )
{
    var o = oControlHost.configuration;
    var margin = {top: 20, right: 150, bottom: 30, left: 80},
        width = 1040 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

    var x = d3.scaleLinear()
        .domain( [0, d3.max( this.m_aValues )])
        .range( [0, width] );

    var y = d3.scaleBand()
    //  .domain(data.map(function(d) { return this.m_aLabels;}))
        .rangeRound([height, 0])
        .padding(0.1);

    var xAxis = d3.axisBottom(x);

    var yAxis = d3.axisLeft(y);

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

    svg.selectAll( ".bar" )
    .data( this.m_aValues)
    .enter().append( "rect" )
    .attr("class", "bar")
    .attr("y", function(d) { return this.m_aLabels; })
    .attr( "width", function(d) { return x(d); } )
    .attr( "height", y.bandwidth())
    .text( function( d ) { return d; } );

    svg.append("g")
      .attr("class", "y axis")
      .call((yAxis)
        .tickSize(3)
        .tickPadding(6));
};

D3BarChart.prototype.setData = function( oControlHost, oDataStore )
{
               this.m_oDataStore = oDataStore;
               this.m_aValues = [];
               this.m_aLabels = [];
               var iRowCount = oDataStore.rowCount;
               for ( var iRow = 0; iRow < iRowCount; iRow++ )
               {
                              this.m_aLabels.push( oDataStore.getCellValue( iRow, 0 ) );
                              this.m_aValues.push( oDataStore.getCellValue( iRow, 1 ) );
               }
};

return D3BarChart;
});

Solution

  • Your data isn't appropriate. It looks like you have two arrays, you need one array with each data-point:

    this.data = [];
    var iRowCount = oDataStore.rowCount;
    for ( var iRow = 0; iRow < iRowCount; iRow++ )
    {
      this.data.push( {label: oDataStore.getCellValue( iRow, 0 ), value: oDataStore.getCellValue( iRow, 1 ) } );
    }
    

    Then your domains become:

    var x = d3.scaleLinear()
        .domain( [0, d3.max(this.data, function(d) { return d.value; } ])
        .range( [0, width] );
    
    var y = d3.scaleBand()
        .domain(this.data.map(function(d) { return d.label; }))
        .rangeRound([height, 0])
        .padding(0.1);
    

    Finally your bars become;

    svg.selectAll( ".bar" )
      .data( this.data )
      .enter().append( "rect" )
      .attr("class", "bar")
      .attr("y", function(d) { return y(d.label); })
      .attr( "width", function(d) { return x(d.value); } )
      .attr( "height", y.bandwidth())
      .text( function( d ) { return d.label; } );