feat(docs): Add state page
This commit is contained in:
@@ -72,6 +72,7 @@ export default defineUserConfig<DefaultThemeOptions>({
|
||||
'/guide/',
|
||||
'/guide/getting-started',
|
||||
'/guide/theming',
|
||||
'/guide/state',
|
||||
{
|
||||
text: 'Nodes',
|
||||
link: '/guide/node/',
|
||||
|
||||
@@ -85,20 +85,6 @@ A basic setup would look like this:
|
||||
</CodeGroupItem>
|
||||
</CodeGroup>
|
||||
|
||||
### State updates
|
||||
|
||||
State updates like removing elements or updating positions are done by default. If you want to strictly control state
|
||||
changes you can disable this behavior by setting the `applyDefault` option/prop to `false`.
|
||||
|
||||
```vue:no-line-numbers
|
||||
<div style="height: 300px">
|
||||
<VueFlow v-model="elements" :apply-default="false" />
|
||||
</div>
|
||||
```
|
||||
|
||||
To take control of state changes you can implement your own state update handlers or use the state helper functions that
|
||||
come with the library to mix it up.
|
||||
|
||||
## TypeScript
|
||||
|
||||
Vue Flow is fully written in [TypeScript](https://www.typescriptlang.org/), so it is highly recommended to use TypeScript to have the best possible DX and
|
||||
|
||||
@@ -8,8 +8,7 @@ Each node <span class="font-bold text-blue-500">requires a unique id and
|
||||
a [xy-position](https://types.vueflow.dev/interfaces/XYPosition.html).</span>
|
||||
Anything else is optional.
|
||||
|
||||
You can check the full options for a node element in the TypeDocs [here](https://types.vueflow.dev/interfaces/Node.html)
|
||||
.
|
||||
You can check the full options for a node element in the TypeDocs [here](https://types.vueflow.dev/interfaces/Node.html).
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
147
docs/src/guide/state.md
Normal file
147
docs/src/guide/state.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# State
|
||||
|
||||
Under the hood Vue Flow uses [Provide/Inject](https://v3.vuejs.org/guide/component-provide-inject.html)
|
||||
to pass around it's state between components.
|
||||
You can access the internal state through the `useVueFlow` composable.
|
||||
|
||||
`useVueFlow` can be used to either create a new state instance and inject it into the current component tree or inject
|
||||
an already existing store from the current context.
|
||||
Internal state can be manipulated, for example by adding new elements to the state. The
|
||||
state is reactive and changes will be reflected on the graph.
|
||||
|
||||
```vue:no-line-numbers{4-6}
|
||||
<script setup>
|
||||
import { useVueFlow } from '@braks/vue-flow'
|
||||
|
||||
const { getNodes, onPaneReady } = useVueFlow({
|
||||
... // you can pass any VueFlowProp to the composable as a static option
|
||||
})
|
||||
|
||||
// event handler
|
||||
onPaneReady((i) => i.fitView())
|
||||
|
||||
// watch the stored nodes
|
||||
watch(getNodes, (nodes) => console.log('nodes changed', nodes))
|
||||
</script>
|
||||
```
|
||||
|
||||
## Accessing internal state
|
||||
|
||||
Using the composition API also allows us to pass the state around outside the current component context, thus we have a lot more flexibility when it comes
|
||||
to reading, writing and updating the state.
|
||||
|
||||
Consider this example, where we want to create a Sidebar that allows us to select all nodes.
|
||||
|
||||
```vue:no-line-numbers
|
||||
<!-- Container.vue -->
|
||||
<template>
|
||||
<div>
|
||||
<Sidebar />
|
||||
<div class="wrapper">
|
||||
<VueFlow v-model="elements" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
We could pass all necessary info as props to the Sidebar, which could become either tedious or result in prop drilling, which we want to avoid.
|
||||
In this example it wouldn't be a big issue but if our destination was 3 components deep, it would become hard to track the flow of information.
|
||||
|
||||
Instead, we can initialize a Vue Flow store instance __before__ the Sidebar is initialized, thus the instance becomes available as an injection in the component tree.
|
||||
|
||||
```vue:no-line-numbers{5-6}
|
||||
<script>
|
||||
// Container.vue
|
||||
import { useVueFlow } from '@braks/vue-flow'
|
||||
|
||||
// initialize a store instance in this context, so it is available when calling inject(VueFlow)
|
||||
useVueFlow()
|
||||
</script>
|
||||
```
|
||||
|
||||
Now we can easily access our current state instance from our Sidebar without passing them as props.
|
||||
|
||||
```vue:no-line-numbers
|
||||
<script setup>
|
||||
import { useVueFlow } from '@braks/vue-flow'
|
||||
|
||||
const { nodesSelectionActive, addSelectedNodes, getNodes } = useVueFlow()
|
||||
|
||||
const selectAll = () => {
|
||||
addSelectedNodes(getNodes.value)
|
||||
nodesSelectionActive.value = true
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<aside>
|
||||
<div class="description">
|
||||
This is an example of how you can access the internal state outside of the Vue VueFlow component.
|
||||
</div>
|
||||
<div class="selectall">
|
||||
<button @click="selectAll">select all nodes</button>
|
||||
</div>
|
||||
</aside>
|
||||
</template>
|
||||
```
|
||||
|
||||
::: tip
|
||||
If you have multiple store instances in the same context, make sure to give them a unique id in order to guarantee access to the correct instance.
|
||||
Otherwise `useVueFlow` will try to inject the first instance it can find in the current context, which would usually be the last one that has been injected.
|
||||
:::
|
||||
|
||||
## Updates
|
||||
|
||||
State updates like removing elements or updating positions are applied by default.
|
||||
If you want to strictly control state changes you can disable this behavior by setting the `applyDefault` option/prop to `false`.
|
||||
|
||||
```vue:no-line-numbers
|
||||
<div style="height: 300px">
|
||||
<VueFlow v-model="elements" :apply-default="false" />
|
||||
</div>
|
||||
```
|
||||
|
||||
State changes are emitted by the `onNodesChange` or `onEdgesChange` events, which will provide an array of changes that have been triggered.
|
||||
To take control of state changes you can implement your own state update handlers or use the state helper functions that
|
||||
come with the library to mix it up.
|
||||
|
||||
## Access state in options API
|
||||
|
||||
`useVueFlow` was designed to be used in the composition API, __but__ it is still possible to use it in the options API.
|
||||
Though it is necessary to pass a unique id for your Vue Flow state instance, otherwise a look-up will fail and Vue Flow will create a new state instance
|
||||
when mounted.
|
||||
|
||||
```vue:no-line-numbers{4,32}
|
||||
<script>
|
||||
import { VueFlow, useVueFlow } from '@braks/vue-flow'
|
||||
|
||||
const { addEdges, onConnect } = useVueFlow({ id: 'options-api' })
|
||||
export default defineComponent({
|
||||
components: { VueFlow },
|
||||
data() {
|
||||
return {
|
||||
elements: [
|
||||
{
|
||||
id: '1',
|
||||
label: 'Node 1',
|
||||
position: { x: 0, y: 0},
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// regular event handler
|
||||
handleConnect: (params) => {
|
||||
addEdges([params])
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
// Register your event handler, can technically be called in any lifecycle phase
|
||||
// Skip this if you're using regular event handlers
|
||||
onConnect((params) => addEdges([params]))
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<VueFlow v-model="elements" id="options-api" @connect="handleConnect" />
|
||||
</template>
|
||||
```
|
||||
Reference in New Issue
Block a user