Prevent inheritance of unwanted data with select.select

In d3, selection.select has the side effect of inheriting data from the parent nodes in the original selection. This is desirable in situations where the data is distributed between the parent and child nodes, so that updated data bound to the parent will be transferred to the child without the need to merge the data at each level.

But what about situations where there is clearly no relationship between the data associated with the parent and the data associated with the child? In this situation, selection.select can be insidious because simply by selecting a node, you cause the node data to be knocked down with unrelated parent data.

What is the best way to avoid this? I can come up with a couple of options, but none of them look great:

  • Always use selection.selectAll everywhere except when explicit data inheritance is required. However, this is not ideal, because using selection.select not compatible with d3.select , which is just used to select an individual node (exactly what I want to do with selection.select ).

  • Use d3.select with a d3.select selector instead of selection.select to isolate a specific node. The convenience of using selection.select is that it implicitly limits the selection to the descendants of the original selection. Achieving this with a selector is not so good.

Personally, I am not a big fan of the modifying effect of the DOM state in one particular form of some of the most commonly used API functions. I think it would be easier for me to understand if the explicit call, for example selection.update(selector) , was symmetric with selection.append and selection.insert .

But in the current API, I wonder if there is any other mechanism that can be used to effectively break inheritance when using selection.select ?

+6
source share
2 answers

In the end, I presented a question about D3 Github: https://github.com/mbostock/d3/issues/1443 . There is no resolution, but there is (I think) an interesting discussion of the problem. At the very bottom, Mike does offer a job that will work, which I will use here for convenience:

Not a great answer, but one way to prevent data inheritance is to have an intermediate node without related data.

 var intermediary = selection.append("div") .datum(function() { return null; }); 

Then any choice from the intermediary will not transfer data from the parent choice. But, of course, the intermediate node in the DOM is somewhat unsuccessful.

+1
source

You can use:

 d3.select(selection.node().querySelector(selector)) 

See the action in jsfiddle , which extends the selection prototype using the selectWithoutDataPropagation () method.

0
source

Source: https://habr.com/ru/post/950215/


All Articles