简体   繁体   中英

How can I attach dynamic objects to an HTML element?

I am using D3.js to create a chart as described in this simplified example

class MyClass {
   // logic goes here
   // constructor() and other functions defined here.
   doSomething() {
       console.log('something.');
   }
}

function createChart(chartID, data) {
    // creating the SVG and appending it to the body
    var svg = d3.select('body').append('svg')
                     .attr('width',400)
                     .attr('height',400)
                     .attr('id',chartID);

   // instantiating an instance of MyClass to be attached to the SVG
   var anObject = new MyClass();
   svg.myObject = anObject;   // this has no effect


   // code to actually build the chart + math to be done on passed data

   // finally, attach a click event to the svg so that data can be manipulated later on
   svg.on('click',function(){
        var object = d3.select(this).myObject;   //this does not work
        object.doSomething();                   // so this also doesn't work
   });
}

createChart('test1',[1,2,3,4]);   // triggering the createChart() function

I am assuming that the variable svg is treated like any JSON object, so, I thought I could attach any object to it.

Apparently, that is not the case. How can I go about attaching an object to an HTML DOM element, so that I may access the object later?

svg variable is a d3 selection object containing DOM elements.

You can set the datum() of the svg and later retrieve it

function createChart(chartID, data) {
    // creating the SVG and appending it to the body
    var svg = d3.select('body').append('svg')
                     .attr('width',400)
                     .attr('height',400)
                     .attr('id',chartID);

   // instantiating an instance of MyClass to be attached to the SVG
   var anObject = new MyClass();
   svg.datum(anObject);


   // code to actually build the chart + math to be done on passed data

   // finally, attach a click event to the svg so that data can be manipulated later on
   svg.on('click',function(){
        var object = d3.select(this).datum();
        object.doSomething();
   });
}

Or use the fact that this in click handler is a DOM element

function createChart(chartID, data) {
    // creating the SVG and appending it to the body
    var svg = d3.select('body').append('svg')
                     .attr('width',400)
                     .attr('height',400)
                     .attr('id',chartID);

   // instantiating an instance of MyClass to be attached to the SVG
   var anObject = new MyClass();
   svg.node().myObject = anObject;


   // code to actually build the chart + math to be done on passed data

   // finally, attach a click event to the svg so that data can be manipulated later on
   svg.on('click',function(){
        var object = this.myObject;
        object.doSomething();
   });
}

Just to add to the already accepted answer , this is a good use for D3 local variables .

According to the API :

D3 locals allow you to define local state independent of data.

So, you can set the local...

var local = d3.local();

local.set(svg.node(), myObject)

... and easily get it:

local.get(svg.node())

That way you don't need to bind unnecessary data (that is, data not related to the visualisation) to the DOM elements.

Here is a demo:

 var local = d3.local(); class MyClass { doSomething() { console.log('something.'); } } function createChart(chartID, data) { var svg = d3.select('body') .append('svg') .attr('width', 200) .attr('height', 200) .attr('id', chartID); var anObject = new MyClass(); local.set(svg.node(), anObject) svg.on('click', function() { local.get(this).doSomething() }); } createChart('test1', [1, 2, 3, 4]); 
 svg { background-color: wheat; } 
 <script src="https://d3js.org/d3.v5.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM