Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 
Not applicable

Build Extension from D3js

Hi Experts,

I'm new to build Qlik Sense Extension from D3js,

I start with two sites below, and the sample worked very well

http://www.axisgroup.com/tutorial-how-to-build-a-qlik-sense-extension-with-d3/

https://community.qlik.com/docs/DOC-16347

So I start to use this sample to build extension

https://bl.ocks.org/mbostock/4062085

But when I finish the code and import the dimensions and measures from test data,

It's always no error but all blank

ex1.JPG

ex2.JPG

I also tried another D3js sample to use, but almost all samples are same problem

This is my code

/*globals define*/

define( ["qlik", "jquery", "text!./style.css", "./d3.v3.min"], function ( qlik, $, cssContent ) {

  'use strict';

  $( "<style>" ).html( cssContent ).appendTo( "head" );

  return {

  initialProperties: {

  qHyperCubeDef: {

  qDimensions: [],

  qMeasures: [],

  qInitialDataFetch: [{

  qWidth: 4,

  qHeight: 1000

  }]

  }

  },

  definition: {

  type: "items",

  component: "accordion",

  items: {

  dimensions: {

  uses: "dimensions",

  min: 3

  },

  measures: {

  uses: "measures",

  min: 1

  },

  sorting: {

  uses: "sorting"

  },

  settings: {

  uses: "settings"

  }

  }

  },

  snapshot: {

  canTakeSnapshot: true

  },

  paint: function ( $element, layout ) {

    //console.log($element);

    //console.log(layout);

    // get qMatrix data array

    var qMatrix = layout.qHyperCube.qDataPages[0].qMatrix;

    // create a new array that contains the measure labels

    var measureLabels = layout.qHyperCube.qMeasureInfo.map(function(d) {

        return d.qFallbackTitle;

    });

    // Create a new array for our extension with a row for each row in the qMatrix

    var data = qMatrix.map(function(d) {

        // for each element in the matrix, create a new object that has a property

        // for the grouping dimension, the first metric, and the second metric

        return {

            "Dim1":d[0].qText,

  "Dim2":d[1].qText,

            "Dim3":d[2].qText,

  "Metric1":d[3].qNum

        }

    });

    // Chart object width

    var width = $element.width();

    // Chart object height

    var height = $element.height();

    // Chart object id

    var id = "container_" + layout.qInfo.qId;

    // Check to see if the chart element has already been created

    if (document.getElementById(id)) {

        // if it has been created, empty it's contents so we can redraw it

        $("#" + id).empty();

    }

    else {

        // if it hasn't been created, create it with the appropiate id and size

        $element.append($('<div />;').attr("id", id).width(width).height(height));

    }

viz(data,measureLabels,width,height,id);

  }

  };

} );

var viz = function (data,labels,width,height,id) {

var margin = {top: 20, right: 40, bottom: 30, left: 20},

    width = width - margin.left - margin.right,

    height = height - margin.top - margin.bottom,

    barWidth = Math.floor(width / 19) - 1;

var x = d3.scale.linear()

    .range([barWidth / 2, width - barWidth / 2]);

var y = d3.scale.linear()

    .range([height, 0]);

var yAxis = d3.svg.axis()

    .scale(y)

    .orient("right")

    .tickSize(-width)

    .tickFormat(function(d) { return Math.round(d / 1e6) + "M"; });

// An SVG element with a bottom-right origin.

var svg = d3.select("body").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 + ")");

// A sliding container to hold the bars by birthyear.

var birthyears = svg.append("g")

    .attr("class", "birthyears");

// A label for the current year.

var title = svg.append("text")

    .attr("class", "title")

    .attr("dy", ".71em")

    .text(2000);

  // Compute the extent of the data set in age and years.

  var age1 = d3.max(data, function(d) { return d.Dim2; }),

      year0 = d3.min(data, function(d) { return d.Dim1; }),

      year1 = d3.max(data, function(d) { return d.Dim1; }),

      year = year1;

  // Update the scale domains.

  x.domain([year1 - age1, year1]);

  y.domain([0, d3.max(data, function(d) { return d.Matric1; })]);

  // Produce a map from year and birthyear to [male, female].

  data = d3.nest()

      .key(function(d) { return d.Dim1; })

      .key(function(d) { return d.Dim1 - d.Dim2; })

      .rollup(function(v) { return v.map(function(d) { return d.Matric1; }); })

      .map(data);

  // Add an axis to show the population values.

  svg.append("g")

      .attr("class", "y axis")

      .attr("transform", "translate(" + width + ",0)")

      .call(yAxis)

    .selectAll("g")

    .filter(function(value) { return !value; })

      .classed("zero", true);

  // Add labeled rects for each birthyear (so that no enter or exit is required).

  var birthyear = birthyears.selectAll(".birthyear")

      .data(d3.range(year0 - age1, year1 + 1, 5))

    .enter().append("g")

      .attr("class", "birthyear")

      .attr("transform", function(birthyear) { return "translate(" + x(birthyear) + ",0)"; });

  birthyear.selectAll("rect")

      .data(function(birthyear) { return data[year][birthyear] || [0, 0]; })

    .enter().append("rect")

      .attr("x", -barWidth / 2)

      .attr("width", barWidth)

      .attr("y", y)

      .attr("height", function(value) { return height - y(value); });

  // Add labels to show birthyear.

  birthyear.append("text")

      .attr("y", height - 4)

      .text(function(birthyear) { return birthyear; });

  // Add labels to show age (separate; not animated).

  svg.selectAll(".age")

      .data(d3.range(0, age1 + 1, 5))

    .enter().append("text")

      .attr("class", "age")

      .attr("x", function(age) { return x(year - age); })

      .attr("y", height + 4)

      .attr("dy", ".71em")

      .text(function(age) { return age; });

  // Allow the arrow keys to change the displayed year.

  window.focus();

  d3.select(window).on("keydown", function() {

    switch (d3.event.keyCode) {

      case 37: year = Math.max(year0, year - 10); break;

      case 39: year = Math.min(year1, year + 10); break;

    }

    update();

  });

  function update() {

    if (!(year in data)) return;

    title.text(year);

    birthyears.transition()

        .duration(750)

        .attr("transform", "translate(" + (x(year1) - x(year)) + ",0)");

    birthyear.selectAll("rect")

        .data(function(birthyear) { return data[year][birthyear] || [0, 0]; })

      .transition()

        .duration(750)

        .attr("y", y)

        .attr("height", function(value) { return height - y(value); });

  }

}


and css

.qv-object-PopulationPyramid div.qv-object-content-container {

}

.qv-object-PopulationPyramid svg {

  font: 10px sans-serif;

}

.qv-object-PopulationPyramid .y.axis path {

  display: none;

}

.qv-object-PopulationPyramid .y.axis line {

  stroke: #fff;

  stroke-opacity: .2;

  shape-rendering: crispEdges;

}

.qv-object-PopulationPyramid .y.axis .zero line {

  stroke: #000;

  stroke-opacity: 1;

}

.qv-object-PopulationPyramid .title {

  font: 300 78px Helvetica Neue;

  fill: #666;

}

.qv-object-PopulationPyramid .birthyear,

.age {

  text-anchor: middle;

}

.qv-object-PopulationPyramid .birthyear {

  fill: #fff;

}

.qv-object-PopulationPyramid rect {

  fill-opacity: .6;

  fill: #e377c2;

}

.qv-object-PopulationPyramid rect:first-child {

  fill: #1f77b4;

}

Can any one help me solve this problem?

Thanks!

1 Reply
Not applicable
Author

I find my mistake at

  1. var svg = d3.select("body").append("svg"


It must change to

  1. var svg = d3.select("#"+id).append("svg"


It's worked now!