Monday, May 13, 2024
 Popular · Latest · Hot · Upcoming
146
rated 0 times [  149] [ 3]  / answers: 1 / hits: 5844  / 10 Years ago, sun, may 4, 2014, 12:00:00

I'm learning D3 and have come across an issue using the select operator.



Specifically, why does the following code add the <p> element outside the body, instead of inside it?



var pData1 = d3.select(body).select(p).data([1]).enter().append(p);



I am using a totally blank HTML file with just <head> and <body> tags to test.



<html lang=en>
<head>
<title><!-- Insert your title here --></title>
<script type=text/javascript src=d3.min.js></script>
</head>
<body>

</body>
</html>

More From » jquery

 Answers
2

(This repeats the content from Lars Kotthoff's answer, but I'd spent time creating the demo so I thought I'd still post.)



The problem is that select, unlike selectAll, does not re-define the parent element for elements added in the enter() selection.



d3.select(body).select(p#a)
.data([1])
.enter().append(p).attr(id, a)
.text(This paragraph is appended to <html> (the document root)
because no selectAll statement reset the parent element.);

d3.selectAll(p#b)
.data([1])
.enter().append(p).attr(id, b)
.text(This paragraph is appended to <html>
because the selectAll statement is called directly on the root.);

d3.selectAll(body).select(p#c)
.data([1])
.enter().append(p).attr(id, c)
.text(This paragraph is also appended to <html>
because the last selectAll statement was called directly from the root.);

d3.select(body).selectAll(p#d)
.data([1])
.enter().append(p).attr(id, d)
.text(This paragraph is appended to <body>
because the selectAll statement is a sub-selection of the body selection.);

d3.selectAll(body).selectAll(p#e)
.data([1])
.enter().append(p).attr(id, e)
.text(This paragraph is also appended to <body>
because the final selectAll statement is a sub-selection of the body.);


http://fiddle.jshell.net/eLF4H/



It is unusual to use an enter chain after a select statement (versus selectAll), because usually you are selecting multiple elements if you are going to do a data join. However, if you want to create the element if it doesn't exist or update it if it does, you have two options:




  • use a selectAll statement followed by the data join



    var pdata1 = d3.select(body).selectAll(p#data) 
    //select element if it exists
    .data([dataObject]);
    //join to the current data

    pdata1.enter().append(p).attr(id, data);
    //create element if required

    pdata1.text(function(d){return d.textValue;});
    //set or update the element based on the data

  • use an if statement to create the element if necessary and use .datum() to bind the data



    var pdata1 = d3.select(p#data) 
    //select element if it exists

    if ( pdata1.empty() ) {
    pdata1 = d3.select(body).append(p).attr(id, data);
    //create element if required
    }

    pdata1.datum(dataObject)
    //note that you don't need to put the data into an array
    .text(function(d){return d.textValue;});
    //set or update the element based on the data


[#45553] Saturday, May 3, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
clarkulisesa

Total Points: 422
Total Questions: 93
Total Answers: 112

Location: Austria
Member since Thu, Jan 7, 2021
3 Years ago
clarkulisesa questions
Mon, Feb 24, 20, 00:00, 4 Years ago
Mon, Aug 12, 19, 00:00, 5 Years ago
;