-1

I have created a d3 force layout,and works very well. My mainly code like so:

var nodes = [{id:1, n:'n_1',np:'0'},{id:2, n:'n_2',np:'0'}];//just for demo
//1. set data
var update = svg.selectAll(".node").data(nodes);
//2. enter
update.enter().append("svg:g").attr("class", "node")
.call(function(p){
  p.append("svg:image").attr("class", "nodeimage");
  p.append("svg:text").attr("class", "nodetext");
});
//3. exit
update.exit().remove();

As is known to us, d3.selectAll(".node").data() is my data. Because the child elements of g will inherit the data from the parent data, d3.selectAll(".nodeimage").data() is also my data.Am I right?

In fact, my data nodes is from backend, and the data is updated. For example, some properties like np have been changed from 0 to 1. We consider the result is nodes = [{id:1, n:'n_1',np:'1'},{id:2, n:'n_2',np:'0'}];

I need to call the function above again. However,d3.selectAll(".node").data() is right, while d3.selectAll(".nodeimage").data() is wrong now.

The following code will not work well.

d3.selectAll('.nodeimage').attr("test", function(d){
    //d.np is a wrong value.
});

Any suggestions for me?

Here is my demo of jsfiddle:http://jsfiddle.net/bpKG4/663/

Does
  • 569
  • 6
  • 24
  • 5
    And what's your question? – Gustavo Morales May 20 '16 at 12:33
  • There must be something else going on, somewhere in your code where you edit `np`. Could you post the code for a complete example showing the bug? – tarulen May 20 '16 at 14:11
  • @tarulen My dear friend, I have finished my demo on jsfiddle.Please take a look at it.I need your help,Thanks. – Does May 21 '16 at 08:03
  • @MoralesBatovski I have put my demo link and I'm waiting for your help. – Does May 21 '16 at 08:05
  • Oh,guys,i clarify my problem clearly and the friend tarulen gave me an acceptable answer.Why vote down and close my answer? – Does Sep 13 '16 at 04:48

1 Answers1

1

This is a strange behavior of d3. If I understand correctly (which is not granted), selection.data(...) automatically transfers data to child elements, unless they already have some data binded.

In your case, it means that you need to copy "by hand" the data to each child:

  //select any child node, then:
    .each(function() {
      d3.select(this).datum(d3.select(this.parentNode).datum());
    }) 

NB: in your fiddle, you only set the xlink:href in the enter() selection: this is wrong, you need to set it within the whole update selection.

update.selectAll(".nodeimage") 
          .each(function() {
             d3.select(this).datum(d3.select(this.parentNode).datum());
          }) 
          .attr("xlink:href", function(d){
            var img;
            if(d.np == 1){
                img = "http://www.gravatar.com/avatar/1eccef322f0beef11e0e47ed7963189b/?default=&s=80"
            }else{
                img = "http://www.gravatar.com/avatar/a1338368fe0b4f3d301398a79c171987/?default=&s=80";
            }
            return img;
          });

See here: http://jsfiddle.net/cs4xhs7s/1/

tarulen
  • 2,070
  • 9
  • 14