title: Draw an ERM with Dagre-D3
body: <p>I try to create an ERM with Dagre-D3. The relations should be displayed directly between the entities attributes. (see screenshot). By grouping the attributes in parent nodes I'm quite there, but some of the algorithms in the dagre graphlib separate the attribute nodes to keep linking simple. I wouldn't mind to have slightly more complex links but kept the attributes together...</p>
  
  <pre><code>var width = window.innerWidth,
  initialHeight = window.innerHeight,
  
  svg = d3.select("body div.container svg"),
  inner = svg.append("g");
  
  svg
     .attr('width', width)
     .attr('height', initialHeight);
  
  // Set up zoom support
  var zoom = d3.behavior.zoom().on("zoom", function() {
      inner.attr("transform", "translate(" + d3.event.translate + ")" +
      "scale(" + d3.event.scale + ")");
  });
  svg.call(zoom);
  
  // create graph
  var g = new dagreD3.graphlib.Graph({
          multigraph: false,
          compound: true
  }).setGraph({
      rankdir: "LR",
      edgesep: 25,
      nodesep: 0
  });
  
  // customer entity
  g.setNode('customer',       {label:'customer', class: 'entity-name', labelStyle: 'font-weight:bold;', width: 80});
  g.setNode('customer_parent',{label:'customer_par', width: 80});
  // customer attributes
  g.setNode('cust_id',        {label: 'id', width: 80});
  g.setNode('cust_first_name',{label: 'first_name', width: 80});
  g.setNode('cust_last_name', {label: 'last_name', width: 80});
  g.setNode('cust_city',      {label: 'city', width: 80});
  g.setNode('cust_country',   {label: 'country', width: 80});
  // assign parent
  g.setParent('customer','customer_parent');
  g.setParent('cust_id','customer_parent');
  g.setParent('cust_first_name','customer_parent');
  g.setParent('cust_last_name','customer_parent');
  g.setParent('cust_city','customer_parent');
  g.setParent('cust_country','customer_parent');
  
  // city entity
  g.setNode('city',       {label:'city', class: 'entity-name', labelStyle: 'font-weight:bold;', width: 80});
  g.setNode('city_parent',{label:'city_parent'});
  // city attributes
  g.setNode('city_id',    {label: 'id', width: 80});
  g.setNode('city_name',  {label: 'name', width: 80});
  g.setNode('city_country',{label: 'country', width: 80});
  // assign parent
  g.setParent('city','city_parent');
  g.setParent('city_id','city_parent');
  g.setParent('city_name','city_parent');
  g.setParent('city_country','city_parent');
  
  // country entity
  g.setNode('country',       {label:'country', width: 80, class: 'entity-name', labelStyle: 'font-weight:bold;'});
  g.setNode('country_parent',{label:'country_parent', width: 80});
  // country attributes
  g.setNode('coun_id',  {label: 'id', width: 80});
  g.setNode('coun_name',{label: 'name', width: 80});
  g.setNode('coun_iso',{label: 'iso', width: 80});
  // assign parent
  g.setParent('country','country_parent');
  g.setParent('coun_id','country_parent');
  g.setParent('coun_name','country_parent');
  g.setParent('coun_iso','country_parent');
  
  // set links
  g.setEdge('cust_city','city_id', {label: '', lineInterpolate: 'monotone'});
  g.setEdge('cust_country','city_country', {label: '', lineInterpolate: 'monotone'});
  g.setEdge('cust_country','coun_id', {label: '', lineInterpolate: 'monotone'});
  g.setEdge('city_country','coun_id', {label: '', lineInterpolate: 'monotone'});
  
  // Create the renderer
  var render = dagreD3.render();
  
  // Run the renderer. This is what draws the final graph.
  render(inner, g);
  
  // adjust height
  var initialScale = 1; //0.75;
  
  // Center the graph
  zoom
      .translate([(svg.attr("width") - g.graph().width * initialScale) / 2, 20])
      .scale(initialScale)
      .event(svg);
  </code></pre>
  
  <p>To illustrate what I'm trying to do I created a jsFiddle:
  <a href="https://jsfiddle.net/sfkdscg7/" rel="nofollow noreferrer">ERM with dagre-d3</a></p>
  
  <p>and here comes the screenshot:
  <img src="https://i.stack.imgur.com/ScfBn.png" alt="ERM with dagre-d3, current status"></p>