Reputation: 7474
It's been a while since I picked up d3.js and it seems I'm a bit rusty. I'm trying to do a form where I can add more input fields by clicking +
and removing the existing ones by clicking -
.
To try and discover what I had wrong, I started colouring the enter()
, update and exit()
with green, yellow and red respectively.
The original data array has two elements, so they show up as green:
Then I click on the plus sign which pushes a new element to the array, and I expected to see two yellows and one green, but instead I see all the elements deleted besides the last one, and this repeats if I click + again:
And plus again:
I've compared my code with the classic General Update Pattern and I can't see anything significant apart from the way I set the keys, in which I use the e-mail. This is code I've added to fix another underlying issue where not all the boxes were being added, just one out of each 3.
My commented code is as follows:
var renderFriends = function () {
console.log("Rendering friends:" + friendsList)
var friends = d3.select('.friends-container')
.selectAll('div')
.data(friendsList, function(d,i) {
// this was something I added when I thought the problem were the keys
return d
})
// updates will be yellow
friends.classed("update", true)
var enter = friends.enter()
// Friend box
// all the divs are because I'm using foundation css
// the new class is what marks the font green
var friendBox = enter.append('div').classed('large-12 columns new', true)
friendBox.append('div').classed('large-8 columns', true)
.append("input")
.attr("type", "text")
.attr("value", String)
// Icon box
var iconBox = friendBox.append('div').classed('large-2 left columns', true)
.append("i")
.classed('fi-minus', true)
.on("click", function(d) {
// out of scope for this question
console.log("Removing:" + d)
friendsList.remove(friendsList.indexOf(d))
renderFriends()
})
// exit state should colour the fonts red
friends.exit().classed('remove', true)
}
Upvotes: 0
Views: 57
Reputation: 961
I did a small test with custom styles and this is what got (when I clicked minus button):
All elements have green background since they all have "new" class, the "update" elements have yellow border, and the "remove" red background. So what I've noticed is that you have a various Divs nested, and the problem is that when you do a selectAll('div') is going to select all divs and d3 is expecting for each div element being selected to be a data element corresponding to it.
So if you want to add another element and your friendsList is:
friendsList = ['[email protected]','[email protected]','[email protected]'];
d3.selectAll('div') is going to take 6 divs (when you had 2 friends and added one), and its going to bind only 3 elements because your dataset contains only 3 friends, and its going to target the rest of elements as "exiting".
To solve this, simply change your select using a class like '.friend' and also add it to each element being inserted (only the main container div); Like this:
Upvotes: 1