Getting Started
Prerequisites
Installation
yarn add @braks/vue-flow
npm i --save @braks/vue-flow
Usage
A flow consists of nodes and (optionally) edges. Together we call them elements.
Each element needs a unique id. A node also needs a xy-position. 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/inject. 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 TypeScript, 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.