feat(docs): Add state page

This commit is contained in:
Braks
2022-04-04 10:19:20 +02:00
parent 094c4ff9ae
commit 91416c9898
4 changed files with 149 additions and 16 deletions

View File

@@ -72,6 +72,7 @@ export default defineUserConfig<DefaultThemeOptions>({
'/guide/',
'/guide/getting-started',
'/guide/theming',
'/guide/state',
{
text: 'Nodes',
link: '/guide/node/',

View File

@@ -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

View File

@@ -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
View 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>
```