| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- # Nodes
- Nodes are defined through [FlowNodeEntity](/api/core/flow-node-entity.html)
- ## Node Data
- Can be obtained through `node.toJSON()`
- :::note Basic Structure:
- - id: `string` Node unique identifier, must be unique
- - meta: `object` Node UI configuration information, such as free layout `position` information is stored here
- - type: `string | number` Node type, corresponds to `type` in `nodeRegistries`
- - data: `object` Node form data, can be customized by business
- - blocks: `array` Node branches, using `block` is closer to `Gramming`
- :::
- ```ts pure
- const nodeData: FlowNodeJSON = {
- id: 'xxxx',
- type: 'condition',
- data: {
- title: 'MyCondition',
- desc: 'xxxxx'
- },
- }
- ```
- ## Node Definition
- Node declaration can be used to determine node type and rendering method
- ```tsx pure
- import { FlowNodeRegistry, ValidateTrigger } from '@flowgram.ai/fixed-layout-editor';
- /**
- * Custom node registration
- */
- export const nodeRegistries: FlowNodeRegistry[] = [
- {
- /**
- * Custom node type
- */
- type: 'condition',
- /**
- * Custom node extension:
- * - loop: Extend as loop node
- * - start: Extend as start node
- * - dynamicSplit: Extend as branch node
- * - end: Extend as end node
- * - tryCatch: Extend as tryCatch node
- * - default: Extend as normal node (default)
- */
- extend: 'dynamicSplit',
- /**
- * Node configuration information
- */
- meta: {
- // isStart: false, // Whether it's a start node
- // isNodeEnd: false, // Whether it's an end node, no nodes can be added after end node
- // draggable: false, // Whether draggable, start and end nodes cannot be dragged
- // selectable: false, // Triggers and start nodes cannot be box-selected
- // deleteDisable: true, // Disable deletion
- // copyDisable: true, // Disable copying
- // addDisable: true, // Disable adding
- },
- /**
- * Configure node form validation and rendering,
- * Note: validate uses data and rendering separation to ensure nodes can validate data even without rendering
- */
- formMeta: {
- validateTrigger: ValidateTrigger.onChange,
- validate: {
- title: ({ value }) => (value ? undefined : 'Title is required'),
- },
- /**
- * Render form
- */
- render: () => (
- <>
- <Field name="title">
- {({ field }) => <div className="demo-free-node-title">{field.value}</div>}
- </Field>
- <Field name="content">
- {({ field }) => <input onChange={field.onChange} value={field.value}/>}
- </Field>
- </>
- )
- },
- },
- ];
- ```
- ## Getting Current Rendered Node
- Get node-related methods through [useNodeRender](/api/hooks/use-node-render.html)
- ```tsx pure
- function BaseNode() {
- const { id, type, data, updateData, node } = useNodeRender()
- }
- ```
- ## Creating Nodes
- Create through [FlowOperationService](/api/services/flow-operation-service.html)
- - Add node
- ```ts pure
- const ctx = useClientContext()
- ctx.operation.addNode({
- id: 'xxx', // Must be unique within canvas
- type: 'custom',
- meta: {},
- data: {}, // Form-related data
- blocks: [], // Child nodes
- parent: someParent // Parent node, used for branches
- })
- ```
- - Add after specified node
- ```ts pure
- const ctx = useClientContext()
- ctx.operation.addFromNode(targetNode, {
- id: 'xxx', // Must be unique within canvas
- type: 'custom',
- meta: {},
- data: {}, // Form-related data
- blocks: [], // Child nodes
- })
- ```
- - Add branch node (used for conditional branches)
- ```ts pure
- const ctx = useClientContext()
- ctx.operation.addBlock(parentNode, {
- id: 'xxx', // Must be unique within canvas
- type: 'block',
- meta: {},
- data: {}, // Form-related data
- blocks: [], // Child nodes
- })
- ```
- ## Deleting Nodes
- ```tsx pure
- function BaseNode({ node }) {
- const ctx = useClientContext()
- function onClick() {
- ctx.operation.deleteNode(node)
- }
- return (
- <button onClick={onClick}>Delete</button>
- )
- }
- ```
- ## Updating Node Data
- - Get node data through [useNodeRender](/api/hooks/use-node-render.html) or [node.form](https://flowgram.ai/auto-docs/editor/interfaces/NodeFormProps.html)
- ```tsx pure
- function BaseNode() {
- const { data, updateData, form } = useNodeRender();
- // Corresponds to node's data
- // 1. data or form.values: Corresponds to node's data
- // 2. form.setValueIn('title', 'xxxx'): Update data.title
- // 3. form.getValueIn('title'): Get data.title
- function onChange(e) {
- updateData({
- ...data,
- title: e.target.value
- })
- }
- return <input value={data.title} onChange={onChange}/>
- }
- ```
- - Update form data through Field, see [Form Usage](/guide/advanced/form.html) for details
- ```tsx pure
- function FormRender() {
- return (
- <Field name="title">
- <Input />
- </Field>
- )
- }
- ```
- ## Updating Node ExtInfo Data
- ExtInfo is used to store some UI states. If node engine is not enabled, node data will be stored in extInfo by default
- ```tsx pure
- function BaseNode({ node }) {
- const times = node.getExtInfo()?.times || 0
- function onClick() {
- node.updateExtInfo({ times: times ++ })
- }
- return (
- <div>
- <span>Click Times: {times}</span>
- <button onClick={onClick}>Click</button>
- </div>
- )
- }
- ```
|