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.