node.mdx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. # 节点
  2. 节点通过 [FlowNodeEntity](/api/core/flow-node-entity.html) 定义
  3. ## 节点数据
  4. 通过 `node.toJSON()` 可以获取
  5. :::note 基本结构:
  6. - id: `string` 节点唯一标识, 必须保证唯一
  7. - meta: `object` 节点的 ui 配置信息,如自由布局的 `position` 信息放这里
  8. - type: `string | number` 节点类型,会和 `nodeRegistries` 中的 `type` 对应
  9. - data: `object` 节点表单数据, 业务可自定义
  10. - blocks: `array` 节点的分支, 采用 `block` 更贴近 `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. ## 节点定义
  23. 声明节点可以用于确定节点的类型及渲染方式
  24. ```tsx pure
  25. import { FlowNodeRegistry, ValidateTrigger } from '@flowgram.ai/fixed-layout-editor';
  26. /**
  27. * 自定义节点注册
  28. */
  29. export const nodeRegistries: FlowNodeRegistry[] = [
  30. {
  31. /**
  32. * 自定义节点类型
  33. */
  34. type: 'condition',
  35. /**
  36. * 自定义节点扩展:
  37. * - loop: 扩展为循环节点
  38. * - start: 扩展为开始节点
  39. * - dynamicSplit: 扩展为分支节点
  40. * - end: 扩展为结束节点
  41. * - tryCatch: 扩展为 tryCatch 节点
  42. * - default: 扩展为普通节点 (默认)
  43. */
  44. extend: 'dynamicSplit',
  45. /**
  46. * 节点配置信息
  47. */
  48. meta: {
  49. // isStart: false, // 是否为开始节点
  50. // isNodeEnd: false, // 是否为结束节点,结束节点后边无法再添加节点
  51. // draggable: false, // 是否可拖拽,如开始节点和结束节点无法拖拽
  52. // selectable: false, // 触发器等开始节点不能被框选
  53. // deleteDisable: true, // 禁止删除
  54. // copyDisable: true, // 禁止copy
  55. // addDisable: true, // 禁止添加
  56. },
  57. /**
  58. * 配置节点表单的校验及渲染,
  59. * 注:validate 采用数据和渲染分离,保证节点即使不渲染也能对数据做校验
  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. ## 当前渲染节点获取
  84. 通过 [useNodeRender](/api/hooks/use-node-render.html) 获取节点相关方法
  85. ```tsx pure
  86. function BaseNode() {
  87. const { id, type, data, updateData, node } = useNodeRender()
  88. }
  89. ```
  90. ## 创建节点
  91. 通过 [FlowOperationService](/api/services/flow-operation-service.html) 创建
  92. - 添加节点
  93. ```ts pure
  94. const ctx = useClientContext()
  95. ctx.operation.addNode({
  96. id: 'xxx', // 要保证画布内唯一
  97. type: 'custom',
  98. meta: {},
  99. data: {}, // 表单相关数据
  100. blocks: [], // 子节点
  101. parent: someParent // 父亲节点,分支会用到
  102. })
  103. ```
  104. - 在指定节点之后添加
  105. ```ts pure
  106. const ctx = useClientContext()
  107. ctx.operation.addFromNode(targetNode, {
  108. id: 'xxx', // 要保证画布内唯一
  109. type: 'custom',
  110. meta: {},
  111. data: {}, // 表单相关数据
  112. blocks: [], // 子节点
  113. })
  114. ```
  115. - 添加分支节点 (用于条件分支)
  116. ```ts pure
  117. const ctx = useClientContext()
  118. ctx.operation.addBlock(parentNode, {
  119. id: 'xxx', // 要保证画布内唯一
  120. type: 'block',
  121. meta: {},
  122. data: {}, // 表单相关数据
  123. blocks: [], // 子节点
  124. })
  125. ```
  126. ## 删除节点
  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. ## 更新节点 data 数据
  139. - 通过 [useNodeRender](/api/hooks/use-node-render.html) 或 [node.form](https://flowgram.ai/auto-docs/editor/interfaces/NodeFormProps.html) 获取节点的 data 数据
  140. ```tsx pure
  141. function BaseNode() {
  142. const { data, updateData, form } = useNodeRender();
  143. // 1. data, form.values 对应节点的 data 数据
  144. // 2. form.setValueIn('title', 'xxxx') 修改 data.title
  145. // 3. form.getValueIn('title') 获取 data.title
  146. function onChange(e) {
  147. updateData({
  148. ...data,
  149. title: e.target.value
  150. })
  151. }
  152. return <input value={data.title} onChange={onChange}/>
  153. }
  154. ```
  155. - 通过 Field 更新表单数据, 详细见 [表单的使用](/guide/advanced/form.html)
  156. ```tsx pure
  157. function FormRender() {
  158. return (
  159. <Field name="title">
  160. <Input />
  161. </Field>
  162. )
  163. }
  164. ```
  165. ## 更新节点的 extInfo 数据
  166. extInfo 用于存储 一些 ui 状态, 如果未开启节点引擎,节点的 data 数据会默认存到 extInfo 里
  167. ```tsx pure
  168. function BaseNode({ node }) {
  169. const times = node.getExtInfo()?.times || 0
  170. function onClick() {
  171. node.updateExtInfo({ times: times ++ })
  172. }
  173. return (
  174. <div>
  175. <span>Click Times: {times}</span>
  176. <button onClick={onClick}>Click</button>
  177. </div>
  178. )
  179. }
  180. ```