Diagram Maker with VueJs

2021.08.20

Introduction

Diagram Maker is a JavaScript library for introducing diagram applications into your project. I've wrote about it here, and today we will include it into VueJs project.

Project

Our project is a template Hello World from vue-cli documentation. It contains a HelloWorld component and underneath we will insert our DiagramMaker component.

<template>
  <HelloWorld msg="Diagram Maker with VueJs"/>
  <DiagramMaker></DiagramMaker>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import DiagramMaker from './components/DiagramMaker.vue'

export default {
  name: 'App',
  components: {
    HelloWorld,
    DiagramMaker
  }
}
</script>

Initialization

To initialize diagram-maker we need to pass it a html container and configuration object. Below is the basic code.

import { DiagramMaker } from 'diagram-maker';

const diagramMaker = new DiagramMaker(
  container,
  config,
  optionalParams // { initialData, eventListener, consumerRootReducer, consumerEnhancer }
);

Let's start with VueJs template. We create a main div container and inside of it a div that we will pass to DiagramMaker via reference "diagramRoot", in VueJs it is done by accessing this.$refs['diagramRoot'] of a component.

<template>
  <div id="main">
    <div id="diagram-container" ref="diagramRoot">
    </div>
  </div>
</template>

In script tag we import DiagramMaker and its stylesheet. In case of VueJs the diagram initialization happens in mounted hook and on beforeUnmount it is destroyed. For now we only pass the container. Next we will look at configuration object.

<script>
import { DiagramMaker } from 'diagram-maker'
import 'diagram-maker/dist/diagramMaker.css'

export default {
  name: 'diagramMaker',
  data () {
    return {
      diagram: null
    }
  },
  mounted () {
    this.diagram = new DiagramMaker(
      this.$refs['diagramRoot'],
      {
        // configuration object
      },
      {
        // optionalParams
      }
    )
  },
  beforeUnmount () {
    this.diagram.destroy()
  }
}
</script>

Configuration

Second parameter is a configuration object. This is where node, edge creation logic and connectors configuration goes in.

    {
        options: {
          connectorPlacement: ConnectorPlacement.LEFT_RIGHT,
          showArrowHead: true
        },
        renderCallbacks: {
          node: (node, container) => {
            const newDiv = document.createElement('div')
            newDiv.classList.add('rectangle', 'example-node')
            return newDiv
          }
        },
        nodeTypeConfig: {
          'node-start': {
            size: { width: 150, height: 50 },
            visibleConnectorTypes: VisibleConnectorTypes.OUTPUT_ONLY
          },
          'node-end': {
            size: { width: 150, height: 50 },
            visibleConnectorTypes: VisibleConnectorTypes.INPUT_ONLY
          }
        }
    }

The 'options' parameter is where we define connector placement (left-right or top-bottom) and wether we want edges' arrow head to be rendered or not.

'renderCallbacks' is where the node creation logic goes in and here we create very simple node.

The 'nodeTypeConfig' is where we define size and connector type on specific nodes. 'node-start' is a output kind of node with a connector from which an edge starts, and 'node-end' is the input node with a connector in which edge ends.

Last parameter of the configuration object are optional parameters but it is the place where initial data goes in. We will insert 2 nodes, one output and one input node, and an edge connecting them.

    {
        initialData: {
          nodes: {
            start: {
              id: 'start',
              typeId: 'node-start',
              diagramMakerData: {
                position: { x: 200, y: 150 },
                size: { width: 100, height: 50 }
              }
            },
            end: {
              id: 'end',
              typeId: 'node-end',
              diagramMakerData: {
                position: { x: 400, y: 150 },
                size: { width: 100, height: 50 }
              }
            }
          },
          edges: {
            edge1: {
              id: 'edge1',
              src: 'start',
              dest: 'end',
              diagramMakerData: { }
            }
          }
        }
    }

Before we run our code there is styling that needs to be done. This will render the workspace in full width of the page.

<style scoped>
#main {
  height: 100%;
  width: 100%;
  top: 120px;
  left: 0;
  position: absolute;
}
#diagram-container {
  height: 100%;
  width: 100%;
  position: relative;
  overflow: hidden;
}
#main /deep/ .dm-node {
  border: 1px solid black !important;
}
</style>

Run it

Here it is. Two nodes, one edge and a VueJs with diagram rendered component.

Conclusion

Diagram maker is a javascript library for creating diagrams. It works with all javascript frameworks as well as with vanilla javascript. We created a VueJs component and included a diagram using the library. We also implemented simple logic for creating nodes and configured them along with edges.