JQuery question. Insertion of D3 charts into multiple SVGs built dynamically
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

Cordova app is dynamically building D3 charts which are inserted into a dynamically built page. It's successfully building the chart and inserting into one the first SVG location in the DOM. Additional charts built are going to the same position, not to the additional entries.

$(deviceId + ' .device-rssi')
  .text(device.rssi)

$(deviceId + ' .device-distance-bar')
  .css('width', distanceBarValue + 'px')

$(deviceId + ' .device-cell_chart')
.text(JSON.stringify(device.advertisementData.cell_chart))

    // Create HTML element to display device data.
var domId = getDeviceDomId(device);
console.log('Create device DOM: ' + domId);
var element = $(
  '<div id="' + domId + '" class="mdl-card mdl-card--border mdl-shadow--2dp">'
  +  '<div class="mdl-card__title">'
  +    '<h2 class="mdl-card__title-text">Device: ' + device.name + '</h2>'
  +  '</div>'
  +  '<div class="mdl-card__supporting-text">'
  +    'Current: <span class="device-current"></span><br>'
  +    'Voltage: <span class="device-voltage"></span><br>'
  +    'Minimum cell voltage: <span class="device-mincellV"></span><br>'
  +    'Maximum cell voltage: <span class="device-maxcellV"></span><br>'
  +    'Remaining watt-hours: <span class="device-energy"></span><br>'
  +    'RSSI: <span class="device-rssi"></span><br>'
  +    ' <div id="cell_chart" class="with-3d-shadow with-transitions">'
  +    ' <svg width="480" height="400"></svg>'
  +    ' </div>'
  +     '<div class="device-distance-bar" style="width:0px;height:10px;margin-top:20px;background:rgb(200,200,0)"></div>'
  +  '</div>'
  + '</div>')

// Add element.
$('.app-cards').append(element)

function barchart(device) {
  nv.addGraph(function() {
    device.cell_chart = nv.models.multiBarChart()
       .margin({left: 60, top: 50, right: 30, bottom: 20})
       .showControls(false)
       .showLegend(false)
       .useInteractiveGuideline(true)
       .duration(1000);
    device.cell_chart.width(window.innerWidth-60);
    device.cell_chart.xAxis
        .tickFormat(d3.format(',f'));
    device.cell_chart.yAxis
        .axisLabel('Voltage (v)')
        .tickFormat(d3.format(',.1f'));
    d3.select('#cell_chart svg')
        .datum(cellData(device))
        .transition().duration(1000)
        .call(device.cell_chart);
    nv.utils.windowResize(device.cell_chart.update);
    return device.cell_chart;
  });
};
awarded to kerncy
Tags
jQuery
d3js

Crowdsource coding tasks.

1 Solution

Winning solution

Hello

your issue comes from the line

d3.select('#cell_chart svg')

This tells d3js to load data in the "#cell_chart" div in the "svg" element.
As you cannot have multiple id with the same name, it always take the first div with its inner svg.

you will have to update your js that create the element by updating the div id :

  +    ' <div id="cell_chart" class="with-3d-shadow with-transitions">'

becomes

  +    ' <div id="' + domId + 'cell_chart" class="with-3d-shadow with-transitions">'

than your

function barchart(device) {

must take the domId in parameters

function barchart(device, domId) {

and update the select part from :

d3.select('#cell_chart svg')

to

d3.select('#' + domId +'cell_chart svg')

When you call your barChart function, you will pass the div id where you want your svg to be inserted.

Do not hesitate if you have any questions