Place a select option inside a div with d3.js

1

I am trying to place a drop-down list (with select and option ) within a div and an SVG using d3.js, but it does not work and the select is not seen. I do not know if they are the properties or the reason why it happens. How can I do it?

This is the code I'm using:

  

Note: the code comes from a question that was previously deleted and is also available in this JSFiddle .

var data = [
  {"id":1,"text":"LAND1"},
  {"id":2,"text":"LAND2"},
  {"id":1,"text":"LAND3"}
];

var vis = d3.select(".dashboard")
            .select("#sowing")
            .append("div")
            .append("svg")
            .attr("id", "chartID")
            .attr("class", "boxing")
            .attr("preserveAspectRatio", "xMinYMin meet")
            .attr("viewBox", "0 0 540 250")
            .append("g")
            .attr("transform", "translate(" + 550 / 2 + "," + 300 / 2 + ")");

var select = vis.append('select')
                .attr("name", "dept-list")
                .attr("class", "form-control");

var options = select.selectAll('option')
                    .data(data)
                    .enter()
                    .append('option')
                    .text(function(d) {
                      return d.text;
                    })
                    .attr("value", function(d) {
                      return d.id;
                    });
#chartID {
  border: 1px solid #D4D4D4;
  background-color: #FFFFFF;
  border-radius: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

<section class="content">
  <div class="col-lg-12">
    <div class="dashboard">
    <div id="sowing"></div>
    </div>
  </div>
</section>
    
asked by Alvaro Montoro 30.11.2016 в 05:28
source

1 answer

2

The problem is doing this:

var vis = d3.select(".dashboard")
            .select("#sowing")
            .append("div")
            .append("svg")
            ....

The variable vis does not contain a div but a svg that is the last element that was added. Then the select is being put inside a svg and it is not shown, because the HTML elements are not proper of SVG, then they are ignored and not shown (although if you look at the code, you will see that they are there).

One possibility would be to move the select to outside the svg and position it absolutely wherever you want. Then you could put it on top of the SVG and it would look good (although technically it will not be inside the SVG).

Another alternative would be to use foreignObject . In SVG you can place non-SVG code (for example HTML) inside an SVG using foreignObject (which literally translates as a foreign or foreign object) and will execute in the proper way. Then you would have to put the select within a foreignObject in the SVG so that it is then interpreted.

You only have to change these lines of code (the rest would remain the same):

// primero coloca un foreignObject
var fo = vis.append("foreignObject")
            .attr("width", 100)
            .attr("height", 100);

// y luego el select dentro del foreign object
var select = fo.append('xhtml:select')
               .attr("name", "dept-list")
               .attr("class", "form-control");

Note that it is very important that the foreignObject have a width and height (minimum of 1) or its content will not be displayed. Also, note how I have put the prefix xhtml: to select to be interpreted correctly (otherwise it would not be seen).

The complete result would look like this:

var data = [
  {"id":1,"text":"LAND1"},
  {"id":2,"text":"LAND2"},
  {"id":1,"text":"LAND3"}
];

var vis = d3.select(".dashboard")
            .select("#sowing")
            .append("div")
            .append("svg")
            .attr("id", "chartID")
            .attr("class", "boxing")
            .attr("preserveAspectRatio", "xMinYMin meet")
            .attr("viewBox", "0 0 540 250")
            .append("g")
            .attr("transform", "translate(" + 550 / 2 + "," + 300 / 2 + ")");

var fo = vis.append("foreignObject")
            .attr("width", 1)
            .attr("height", 1);
          
var select = fo.append('xhtml:select')
               .attr("name", "dept-list")
               .attr("class", "form-control");


var options = select.selectAll('option')
                    .data(data)
                    .enter()
                    .append('option')
                    .text(function(d) {
                      return d.text;
                    })
                    .attr("value", function(d) {
                      return d.id;
                    });
#chartID {
  border: 1px solid #D4D4D4;
  background-color: #FFFFFF;
  border-radius: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

<section class="content">
  <div class="col-lg-12">
    <div class="dashboard">
    <div id="sowing"></div>
    </div>
  </div>
</section>
    
answered by 30.11.2016 / 05:28
source