node.mdx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. # Nodes
  2. Nodes are defined through [FlowNodeEntity](/api/core/flow-node-entity.html)
  3. ## Node Data
  4. Can be obtained through `node.toJSON()`
  5. :::note Basic Structure:
  6. - id: `string` Node unique identifier, must be unique
  7. - meta: `object` Node UI configuration information, such as free layout `position` information is stored here
  8. - type: `string | number` Node type, corresponds to `type` in `nodeRegistries`
  9. - data: `object` Node form data, can be customized by business
  10. - blocks: `array` Node branches, using `block` is closer to `Gramming`
  11. :::
  12. ```ts pure
  13. const nodeData: FlowNodeJSON = {
  14. id: 'xxxx',
  15. type: 'condition',
  16. data: {
  17. title: 'MyCondition',
  18. desc: 'xxxxx'
  19. },
  20. }
  21. ```
  22. ## Node Definition
  23. Node declaration can be used to determine node type and rendering method
  24. ```tsx pure
  25. import { FlowNodeRegistry, ValidateTrigger } from '@flowgram.ai/fixed-layout-editor';
  26. /**
  27. * Custom node registration
  28. */
  29. export const nodeRegistries: FlowNodeRegistry[] = [
  30. {
  31. /**
  32. * Custom node type
  33. */
  34. type: 'condition',
  35. /**
  36. * Custom node extension:
  37. * - loop: Extend as loop node
  38. * - start: Extend as start node
  39. * - dynamicSplit: Extend as branch node
  40. * - end: Extend as end node
  41. * - tryCatch: Extend as tryCatch node
  42. * - default: Extend as normal node (default)
  43. */
  44. extend: 'dynamicSplit',
  45. /**
  46. * Node configuration information
  47. */
  48. meta: {
  49. // isStart: false, // Whether it's a start node
  50. // isNodeEnd: false, // Whether it's an end node, no nodes can be added after end node
  51. // draggable: false, // Whether draggable, start and end nodes cannot be dragged
  52. // selectable: false, // Triggers and start nodes cannot be box-selected
  53. // deleteDisable: true, // Disable deletion
  54. // copyDisable: true, // Disable copying
  55. // addDisable: true, // Disable adding
  56. },
  57. /**
  58. * Configure node form validation and rendering,
  59. * Note: validate uses data and rendering separation to ensure nodes can validate data even without rendering
  60. */
  61. formMeta: {
  62. validateTrigger: ValidateTrigger.onChange,
  63. validate: {
  64. title: ({ value }) => (value ? undefined : 'Title is required'),
  65. },
  66. /**
  67. * Render form
  68. */
  69. render: () => (
  70. <>
  71. <Field name="title">
  72. {({ field }) => <div className="demo-free-node-title">{field.value}</div>}
  73. </Field>
  74. <Field name="content">
  75. {({ field }) => <input onChange={field.onChange} value={field.value}/>}
  76. </Field>
  77. </>
  78. )
  79. },
  80. },
  81. ];
  82. ```
  83. ## Getting Current Rendered Node
  84. Get node-related methods through [useNodeRender](/api/hooks/use-node-render.html)
  85. ```tsx pure
  86. function BaseNode() {
  87. const { id, type, data, updateData, node } = useNodeRender()
  88. }
  89. ```
  90. ## Creating Nodes
  91. Create through [FlowOperationService](/api/services/flow-operation-service.html)
  92. - Add node
  93. ```ts pure
  94. const ctx = useClientContext()
  95. ctx.operation.addNode({
  96. id: 'xxx', // Must be unique within canvas
  97. type: 'custom',
  98. meta: {},
  99. data: {}, // Form-related data
  100. blocks: [], // Child nodes
  101. parent: someParent // Parent node, used for branches
  102. })
  103. ```
  104. - Add after specified node
  105. ```ts pure
  106. const ctx = useClientContext()
  107. ctx.operation.addFromNode(targetNode, {
  108. id: 'xxx', // Must be unique within canvas
  109. type: 'custom',
  110. meta: {},
  111. data: {}, // Form-related data
  112. blocks: [], // Child nodes
  113. })
  114. ```
  115. - Add branch node (used for conditional branches)
  116. ```ts pure
  117. const ctx = useClientContext()
  118. ctx.operation.addBlock(parentNode, {
  119. id: 'xxx', // Must be unique within canvas
  120. type: 'block',
  121. meta: {},
  122. data: {}, // Form-related data
  123. blocks: [], // Child nodes
  124. })
  125. ```
  126. ## Deleting Nodes
  127. ```tsx pure
  128. function BaseNode({ node }) {
  129. const ctx = useClientContext()
  130. function onClick() {
  131. ctx.operation.deleteNode(node)
  132. }
  133. return (
  134. <button onClick={onClick}>Delete</button>
  135. )
  136. }
  137. ```
  138. ## Updating Node Data
  139. - Get node data through [useNodeRender](/api/hooks/use-node-render.html) or [node.form](https://flowgram.ai/auto-docs/editor/interfaces/NodeFormProps.html)
  140. ```tsx pure
  141. function BaseNode() {
  142. const { data, updateData, form } = useNodeRender();
  143. // Corresponds to node's data
  144. // 1. data or form.values: Corresponds to node's data
  145. // 2. form.setValueIn('title', 'xxxx'): Update data.title
  146. // 3. form.getValueIn('title'): Get data.title
  147. function onChange(e) {
  148. updateData({
  149. ...data,
  150. title: e.target.value
  151. })
  152. }
  153. return <input value={data.title} onChange={onChange}/>
  154. }
  155. ```
  156. - Update form data through Field, see [Form Usage](/guide/advanced/form.html) for details
  157. ```tsx pure
  158. function FormRender() {
  159. return (
  160. <Field name="title">
  161. <Input />
  162. </Field>
  163. )
  164. }
  165. ```
  166. ## Updating Node ExtInfo Data
  167. ExtInfo is used to store some UI states. If node engine is not enabled, node data will be stored in extInfo by default
  168. ```tsx pure
  169. function BaseNode({ node }) {
  170. const times = node.getExtInfo()?.times || 0
  171. function onClick() {
  172. node.updateExtInfo({ times: times ++ })
  173. }
  174. return (
  175. <div>
  176. <span>Click Times: {times}</span>
  177. <button onClick={onClick}>Click</button>
  178. </div>
  179. )
  180. }
  181. ```