Taking Control of Vue Flow ​
WARNING
This API is subject to change in the next major release where changes will not be applied automatically anymore.
By default, Vue Flow will apply changes automatically, so you don't have to worry about it.
Though, there are cases where you want to take control of changes and apply them manually after some processing and validations for example.
In this guide, we will learn how to take control of changes and apply them manually.
What is a Change? ​
A change is anything that is triggered by an interaction with the flow, like adding, updating (position, selected), or removing a node or an edge, either by dragging, clicking etc. or by using the provided API.
These changes are communicated to the user-land through the onNodesChange
and onEdgesChange
events.
Possible Changes include:
add
: A node or an edge was added.remove
: A node or an edge was removed.select
: A node or an edge was selected/unselected.position
: A nodes' position was updated.dimensions
: A nodes' dimensions were updated.
WARNING
Changes do not refer to any change in the flow, like zooming or panning, or just updating the data
object of a node.
Why is no change emitted when I update a node? ​
Vue Flow will not track your nodes/edges and try to figure out what changed, it will only emit changes when you interact with the flow or use the API.
For example this will not emit a change:
<script setup>
import { ref } from 'vue'
const nodes = ref([
{
id: '1',
position: { x: 0, y: 0 },
data: { label: 'Node 1' },
},
])
// this function *will not* emit a change
function removeNode() {
nodes.value = nodes.value.filter((node) => node.id !== '1')
}
</script>
This is because Vue Flow does not know that the node with id 1
was removed, it only knows about changes that are triggered by the user or the API.
This, for example, will emit a change:
<script setup>
import { ref } from 'vue'
import { useVueFlow } from '@vue-flow/core'
const nodes = ref([
{
id: '1',
position: { x: 0, y: 0 },
data: { label: 'Node 1' },
},
])
// this function *will* emit a change
const { removeNodes } = useVueFlow()
removeNodes('1')
</script>
The applyDefault
option ​
The applyDefault
option is a prop that can be passed to the <VueFlow>
component to enable or disable automatic change handling.
By setting this option to false
, we tell Vue Flow to not apply changes automatically anymore, that way we can take control of changes and apply them manually.
<template>
<VueFlow :nodes="nodes" :edges="edges" :apply-default="false" />
</template>
onNodesChange
/ onEdgesChange
events ​
Vue Flow provides two events that can be used to listen to changes on nodes and edges. These events are emitted regardless of the applyDefault
option, so you can use them to listen to changes even if you have automatic changes enabled.
<script setup>
import { VueFlow, useVueFlow } from '@vue-flow/core'
const { onNodesChange, onEdgesChange } = useVueFlow()
onNodesChange((changes) => {
// changes are arrays of type `NodeChange`
console.log(changes)
})
onEdgesChange((changes) => {
// changes are arrays of type `EdgeChange`
console.log(changes)
})
const onChange = (changes) => {
// changes are arrays of type `NodeChange` or `EdgeChange`
console.log(changes)
}
</script>
<template>
<VueFlow :nodes="nodes" :edges="edges" @nodes-change="onChange" @edges-change="onChange" />
</template>
applyNodeChanges
/ applyEdgeChanges
​
Vue Flow provides two functions that can be used to apply changes manually.
These functions are available from the useVueFlow
composable.
<script setup>
import { useVueFlow } from '@vue-flow/core'
const { applyNodeChanges, applyEdgeChanges } = useVueFlow();
const onChange = (changes) => {
// apply changes manually
applyNodeChanges(changes)
}
</script>
Validating Changes ​
Using what we just learned, we can now take control of changes and apply them manually.
In this example, we will first disable automatic change handlers with applyDefault
, then use the onNodesChange
event to listen to changes and validate delete changes and, if they are valid, use applyNodeChanges
to apply them.
INFO
Checkout the confirm delete example.
<script setup>
import { ref } from 'vue'
import { useVueFlow, VueFlow } from '@vue-flow/core'
const { applyNodeChanges } = useVueFlow();
const { confirm } = useConfirm();
const nodes = ref([
{
id: '1',
position: { x: 0, y: 0 },
data: { label: 'Node 1' },
},
{
id: '2',
position: { x: 100, y: 100 },
data: { label: 'Node 2' },
},
])
const edges = ref([
{
id: 'e1->2',
source: '1',
target: '2',
},
])
const onNodesChange = async (changes) => {
const nextChanges = []
for (const change of changes) {
if (change.type === 'remove') {
const isConfirmed = await confirm('Are you sure you want to delete this node?')
if (isConfirmed) {
nextChanges.push(change)
}
} else {
nextChanges.push(change)
}
}
applyNodeChanges(nextChanges)
}
</script>
<template>
<VueFlow :nodes="nodes" :edges="edges" :apply-default="false" @nodes-change="onNodesChange" />
</template>
V-Model Nodes and Edges ​
In some cases you want to sync the state of internal nodes/edges with your own state, for those cases you can use the v-model
directive to bind the internal state with your own state.
<template>
<VueFlow v-model:edges="edges" v-model:nodes="nodes" />
</template>
Doing this will sync the internal state with your own state, which is useful for situations where you update internal nodes and edges but also want those changes to be reflected in your own state.
For example, if you update the type of nodes using updateNode
and want to see the same change reflected in your own nodes state and not just in the internal state.
<script setup>
import { ref } from 'vue'
import { useVueFlow } from '@vue-flow/core'
const nodes = ref([
{
id: '1',
position: { x: 0, y: 0 },
data: { label: 'Node 1' },
},
])
const { updateNode } = useVueFlow()
// using updateNode will only update the internal state, not the nodes state unless you use v-model
updateNode('1', { type: 'new-type' })
</script>