bitoiu
bitoiu

Reputation: 7474

D3 elements being removed although I'm only adding new ones

It's been a while since I picked up 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:

enter image description here

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:

enter image description here

And plus again:

enter image description here

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

Answers (1)

kevinkl3
kevinkl3

Reputation: 961

I did a small test with custom styles and this is what got (when I clicked minus button):

enter image description here

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:

http://jsfiddle.net/2codv59e/

Upvotes: 1

Related Questions