Why does this D3 code add the

element outside the body, instead of inside it?

后端 未结 3 1561
北恋
北恋 2020-12-30 09:43

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

Specifically, why does the following code add the

element outside th

相关标签:
3条回答
  • 2020-12-30 09:52

    (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
      
    0 讨论(0)
  • 2020-12-30 10:07

    As suggested in the comments, the way to do what you're trying to do is to use .selectAll(). The difference between .select() and .selectAll() is that .select() returns elements while .selectAll() returns elements grouped by ancestor. This then affects any subsequent .data() operations in terms of what the elements are appended to. From the documentation:

    Grouping by selectAll also affects subsequent entering placeholder nodes. Thus, to specify the parent node when appending entering nodes, use select followed by selectAll:

    d3.select("body").selectAll("div")

    0 讨论(0)
  • 2020-12-30 10:11

    there is no p element to select, so I would suggest appending the p element before entering your data:

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

    do whatever else you need to do after .data, although there is no need to append another p

    0 讨论(0)
提交回复
热议问题