Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: smarter appending to enter selection #29

Closed
mgold opened this issue May 23, 2015 · 5 comments
Closed

Proposal: smarter appending to enter selection #29

mgold opened this issue May 23, 2015 · 5 comments

Comments

@mgold
Copy link

mgold commented May 23, 2015

In 3.x it's very common to do something like this:

d3.selectAll("div.myclass")
    .data(myData)
    .enter()
    .append("div")
    .classed("myclass", true)

For brevity I'm assuming we only care about the enter selection, but it's true in general: most of the time we append elements that match the original selector. We have to duplicate the element name and class.

It would be very convenient to have the following be equivalent to the above:

d3.selectAll("div.myclass")
    .data(myData)
    .enter()
    .append()

Currently append always takes arguments, and that would override the selector given. I'm not sure if this proposal is feasible in general, with nested selections (now arbitrary deep I hear?) and complex selectors. But hey, no harm in asking right?

@1wheel
Copy link

1wheel commented May 24, 2015

You can do this (w/ slightly different syntax) in 3 by modifying the selection prototype - see jetpack and starterkit

@mgold
Copy link
Author

mgold commented May 24, 2015

Okay, so that rolls .classed into .append but you still have to specify things twice for an enter selection. So those libraries don't really address the problem.

@mgold
Copy link
Author

mgold commented May 25, 2015

Hmm, I suppose you'd have a bit of a problem for union selectors like "div.a, span.b". I don't think this is a dealbreaker, though. You'd take the last one and most of the time the user would override it. I still would like Mike to weigh in.

@mbostock
Copy link
Member

I typically just select by class and not element:

selection.selectAll(".foo")
    .data(data)
  .enter().append("div")
    .class("foo", true);

Sometimes I’ll do things like select based on the presence of an attribute but then compute its value dynamically:

selection.selectAll("[foo]")
    .data(data)
  .enter().append("div")
    .attr("foo", function(d, i) { return ; });

So, yes, typically the selector used to create a selection implies certain things on entering elements, but not always enough to enforce those things automatically. It would be possible to capture the selector used to create a selection (when a selector is used—note that you can also pass a function to selection.select and selection.selectAll), and then modify enter.select / enter.append to try to enforce what’s implied by the selector.

But, it’s not trivial to enforce that the selector matches materialized elements in general. For example, you presumably wouldn’t be able to enforce a selector like ":nth-child(2)", and in an attribute existence selector (like "[foo]") you’d have to define a default value for that attribute, which might be pointless if you were going to subsequently give it an explicit value later anyway.

Given the difficulty of supporting this in the general case, and the undesirability of having it just work in a few special cases, I prefer having a little redundancy. Or just a little syntactic sugar for convenience as an optional feature, like in d3-jetpack.

@mgold
Copy link
Author

mgold commented May 26, 2015

Okay, thanks for the explanation.

@mgold mgold closed this as completed May 26, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants