D3 V4 - TREE - ADD & REMOVE NODE DYNAMICALLY

by bizamajig

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.7.4/d3.js"></script>
<button id="add-child" disabled="disabled">Add Child</button> 
<button id="remove" disabled="disabled">Remove</button>

JavaScript

// ### DATA MODEL START

var data = {
	type: 'action',
  name: '1',
  attributes: [],
  children: [{
  	type: 'children',
  	name: '2',
    attributes: [{
    	'source-type-property-value': 'streetlight'
    }],
    children: [{
    	type: 'parents',
  		name: '3',
      attributes: [{
      	'source-type-property-value': 'cable'
      }],
      children: [{
      	type: 'resource-delete',
  			name: '4',
        attributes: [],
        children: []
      }]
    }, {
    	type: 'children',
  		name: '5',
      attributes: [{
      	'source-type-property-value': 'lantern'
      }],
      children: []
    }]
  }]
};

// ### DATA MODEL END

// Set the dimensions and margins of the diagram
var margin = {top: 20, right: 90, bottom: 30, left: 90},
	width = 960 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;

// append the svg object to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select("body").
	append("svg").
  attr("width", width + margin.right + margin.left).
  attr("height", height + margin.top + margin.bottom).
  append("g").
  attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var i = 0, duration = 750, root;

// declares a tree layout and assigns the size
var treemap = d3.tree().size([height, width]);

// Assigns parent, children, height, depth
root = d3.hierarchy(data, function(d) {
	return d.children;
});
root.x0 = height / 2;
root.y0 = 0;

update(root);

var selected = null;

function update(source) {

  // Assigns the x and y position for the nodes
  var treeData = treemap(root);

  // Compute the new tree layout.
  var nodes = treeData.descendants(),
  	links = treeData.descendants().slice(1);

  // Normalize for fixed-depth.
  nodes.forEach(function(d){
  	d.y = d.depth * 180
  });

  // ### LINKS

  // Update the links...
  var link = svg.selectAll('line.link').
  	data(links, function(d) {
    	return d.id;
    });

  // Enter...