0
votes

I am working with DC.js and crossfilter. There are two js files in my project. chart1.js is for visualisation#1 and chart2.js is for visualisation#2. I am trying to use a composite chart to combine three bar charts in chart2.js. However, there are two errors in the console. I have no idea why these errors happen.

One error is Uncaught Mandatory attribute chart.dimension is missing on chart[#chart-bar-lifecycleCost].

Another one is Uncaught TypeError: allCostChart.width(...).height(...).dimension(...).group(...).x(...).elasticY(...).centerBar is not a function.

It seems that chart1.js can run smoothly, but chart2.js has the errors mentioned above. Here is part of chart2.js:

var lifecycleCostChart = dc.barChart('#chart-bar-lifecycleCost'),
    plannedCostChart = dc.barChart('#chart-bar-plannedCost'),
    projectedCostChart = dc.barChart('#chart-bar-projectedCost'),
    allCostChart = dc.compositeChart('#chart-composite-allCost'),
    agencyRowChart = dc.rowChart('#chart-agency-row'),
    dataTable2;



d3.csv('/data/Projects_CW1.csv', function (error, data) {

if (error) {
    console.log(error);
}


data.forEach(function (d) {

    d.lifecycleCost = +d["Lifecycle_Cost"];
    d.plannedCost = +d["Planned_Cost"];
    d.projectedCost = +d["Projected_Actual_Cost"];
    d.agnecyName = d["Agency_Name"];

});


var ndx = crossfilter(data);


var lifecycleCostDim = ndx.dimension(function (d) {
        return d["Lifecycle_Cost"];
    }),

    plannedCostDim = ndx.dimension(function (d) {
        return d["Planned_Cost"];
    }),
    projectedCostDim = ndx.dimension(function (d) {
        return d["Projected_Actual_Cost"];
    }),

    agencyNameDim = ndx.dimension(function (d) {
        return d["Agency_Name"]
    }),

    allDim = ndx.dimension(function (d) {
        return d;
    });


var all = ndx.groupAll();

var plannedCostGroup = agencyNameDim.group().reduceSum(function (d) {
        return d.plannedCost;
    }),
    projectedCostGroup = agencyNameDim.group().reduceSum(function (d) {
        return d.projectedCost;
    }),
    lifecycleCostGroup = agencyNameDim.group().reduceSum(function (d) {
        return d.lifecycleCost;
    }),
    agencyNameGroup = agencyNameDim.group().reduceCount();

allCostChart
    .width(500)
    .height(320)
    .dimension(agencyNameDim)
    .group(agencyNameGroup)
    .x(d3.scale.ordinal())
    .elasticY(true)
    .centerBar(true)
    .barPadding(5)
    .brushOn(false)
    .yAxisLabel('Count')
    .xUnits(dc.units.ordinal)
    .compose([
        dc.barChart(allCostChart)
        .centerBar(true)
        .gap(100)
        .colors('red')
        .dimension(lifecycleCostDim)
        .group(lifecycleCostGroup)
        ,
        dc.barChart(allCostChart)
        .centerBar(true)
        .gap(100)
        .colors('blue')
        .dimension(plannedCostDim)
        .group(plannedCostGroup),
        dc.barChart(allCostChart)
        .centerBar(true)
        .gap(100)
        .colors('blue')
        .dimension(projectedCostDim)
        .group(projectedCostGroup)])
    .renderHorizontalGridLines(true)
    .renderVerticalGridLines(true)
    .render();

Here is part of the screenshot of csv file. I want to list these three variances as bars in a composite chart according to different agency names.

part of screenshot of csv file

1

1 Answers

1
votes
  1. You don't need to create separate divs or chart objects for the the different parts of the composite chart. So your lifecycleCostChart and its siblings are not needed. Since you never initialize them, dc.js complains that they are missing attributes.
  2. centerBar is a method of the bar chart, not the composite chart. You should apply it to the child charts, not the composite itself.