Getting Started

Prerequisites

Installation

yarn add @braks/vue-flow
npm i --save @braks/vue-flow

Usage

A flow consists of nodesopen in new window and (optionally) edgesopen in new window. Together we call them elementsopen in new window.

Each element needs a unique id. A node also needs a xy-positionopen in new window. An edge needs at least a source (node id) and a target (node id).

<script setup>
import { VueFlow  } from '@braks/vue-flow'

const elements = ref([
  // Nodes
  // An input node, specified by using `type: 'input'`
  { id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 } },

  // Default nodes, you can omit `type: 'default'`
  { id: '2', label: 'Node 2', position: { x: 100, y: 100 }, },
  { id: '3', label: 'Node 3', position: { x: 400, y: 100 } },

  // An output node, specified by using `type: 'output'`
  { id: '4', type: 'output', label: 'Node 4', position: { x: 400, y: 200 } },

  // Edges
  // Most basic edge, only consists of an id, source-id and target-id
  { id: 'e1-3', source: '1', target: '3' },

  // An animated edge
  { id: 'e1-2', source: '1', target: '2', animated: true },
])
</script>
<template>
  <VueFlow v-model="elements" />
</template>

Quickstart

The recommended method of using Vue Flow is the composition API as it allows for full control of the state, thanks to composables and the power of provide/injectopen in new window. You can even access the state outside the context and manipulate it to your liking. However, using the options API is possible, though more limited it will probably satisfy most of your needs if you are not looking for too advanced handling of states.

A basic setup would look like this:

<script lang="ts" setup>
import type { Elements } from '@braks/vue-flow'
import { Background, Controls, MiniMap, VueFlow, isNode, useVueFlow } from '@braks/vue-flow'

const elements = ref<Elements>([
  { id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 }, class: 'light' },
  { id: '2', label: 'Node 2', position: { x: 100, y: 100 }, class: 'light' },
  { id: '3', label: 'Node 3', position: { x: 400, y: 100 }, class: 'light' },
  { id: '4', label: 'Node 4', position: { x: 400, y: 200 }, class: 'light' },
  { id: 'e1-2', source: '1', target: '2', animated: true },
  { id: 'e1-3', source: '1', target: '3' },
])
const { onPaneReady, onNodeDragStop, onConnect, instance, addEdges } = useVueFlow({
  defaultZoom: 1.5,
  minZoom: 0.2,
  maxZoom: 4,
})

onPaneReady(({ fitView }) => {
  fitView()
})
onNodeDragStop((e) => console.log('drag stop', e))
onConnect((params) => addEdges([params]))

const updatePos = () =>
  elements.value.forEach((el) => {
    if (isNode(el)) {
      el.position = {
        x: Math.random() * 400,
        y: Math.random() * 400,
      }
    }
  })

const logToObject = () => console.log(instance.value?.toObject())
const resetTransform = () => instance.value?.setTransform({ x: 0, y: 0, zoom: 1 })
const toggleclass = () => elements.value.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
</script>

<template>
  <VueFlow v-model="elements" class="vue-flow-basic-example">
    <Background />
    <MiniMap />
    <Controls />
    <div style="position: absolute; right: 10px; top: 10px; z-index: 4">
      <button style="margin-right: 5px" @click="resetTransform">reset transform</button>
      <button style="margin-right: 5px" @click="updatePos">change pos</button>
      <button style="margin-right: 5px" @click="toggleclass">toggle class</button>
      <button @click="logToObject">toObject</button>
    </div>
  </VueFlow>
</template>
<script lang="ts">
import type { Elements, FlowEvents, FlowInstance } from '@braks/vue-flow'
import { Background, Controls, MiniMap, VueFlow, addEdge, isNode } from '@braks/vue-flow'

export default defineComponent({
  name: 'BasicOptionsAPI',
  components: { VueFlow, Background, MiniMap, Controls },
  data() {
    return {
      instance: null as FlowInstance | null,
      elements: [
        { id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 }, class: 'light' },
        { id: '2', label: 'Node 2', position: { x: 100, y: 100 }, class: 'light' },
        { id: '3', label: 'Node 3', position: { x: 400, y: 100 }, class: 'light' },
        { id: '4', label: 'Node 4', position: { x: 400, y: 200 }, class: 'light' },
        { id: 'e1-2', source: '1', target: '2', animated: true },
        { id: 'e1-3', source: '1', target: '3' },
      ] as Elements,
    }
  },
  methods: {
    logToObject() {
      console.log(this.instance?.toObject())
    },
    resetTransform() {
      this.instance?.setTransform({ x: 0, y: 0, zoom: 1 })
    },
    toggleclass() {
      this.elements.forEach((el) => (el.class = el.class === 'light' ? 'dark' : 'light'))
    },
    updatePos() {
      this.elements.forEach((el) => {
        if (isNode(el)) {
          el.position = {
            x: Math.random() * 400,
            y: Math.random() * 400,
          }
        }
      })
    },
    onNodeDragStop(e: FlowEvents['nodeDragStop']) {
      console.log('drag stop', e)
    },
    onPaneReady(instance: FlowEvents['paneReady']) {
      instance.fitView()
      this.instance = instance
    },
    onConnect(params: FlowEvents['connect']) {
      addEdge(params, this.elements)
    },
  },
})
</script>

<template>
  <VueFlow
    v-model="elements"
    class="vue-flow-basic-example"
    :default-zoom="1.5"
    :min-zoom="0.2"
    :max-zoom="4"
    :zoom-on-scroll="false"
    @connect="onConnect"
    @pane-ready="onPaneReady"
    @node-drag-stop="onNodeDragStop"
  >
    <Background />
    <MiniMap />
    <Controls />
    <div style="position: absolute; right: 10px; top: 10px; z-index: 4">
      <button style="margin-right: 5px" @click="resetTransform">reset transform</button>
      <button style="margin-right: 5px" @click="updatePos">change pos</button>
      <button style="margin-right: 5px" @click="toggleclass">toggle class</button>
      <button @click="logToObject">toObject</button>
    </div>
  </VueFlow>
</template>

TypeScript

Vue Flow is fully written in TypeScriptopen in new window, so it is highly recommended to use TypeScript to have the best possible DX and avoid common mistakes. The types are included in the library.

You can find the TypeDocs hereopen in new window.