Browse Source

fix(form): formMeta.render support useWatch, NodeContext -> NodeFormContext (#527)

xiamidaxia 6 months ago
parent
commit
c68ce7c0b6

+ 14 - 0
apps/demo-fixed-layout/src/nodes/default-form-meta.tsx

@@ -31,6 +31,20 @@ export const renderForm = ({ form }: FormRenderProps<FlowNodeJSON['data']>) => (
 export const defaultFormMeta: FormMeta<FlowNodeJSON['data']> = {
   render: renderForm,
   validateTrigger: ValidateTrigger.onChange,
+  /**
+   * Initialize (fromJSON) data transformation
+   * 初始化(fromJSON) 数据转换
+   * @param value
+   * @param ctx
+   */
+  formatOnInit: (value, ctx) => value,
+  /**
+   * Save (toJSON) data transformation
+   * 保存(toJSON) 数据转换
+   * @param value
+   * @param ctx
+   */
+  formatOnSubmit: (value, ctx) => value,
   validate: {
     title: ({ value }) => (value ? undefined : 'Title is required'),
     'inputsValues.*': ({ value, context, formValues, name }) => {

+ 14 - 0
apps/demo-free-layout/src/nodes/default-form-meta.tsx

@@ -48,6 +48,20 @@ export const defaultFormMeta: FormMeta<FlowNodeJSON> = {
       return undefined;
     },
   },
+  /**
+   * Initialize (fromJSON) data transformation
+   * 初始化(fromJSON) 数据转换
+   * @param value
+   * @param ctx
+   */
+  formatOnInit: (value, ctx) => value,
+  /**
+   * Save (toJSON) data transformation
+   * 保存(toJSON) 数据转换
+   * @param value
+   * @param ctx
+   */
+  formatOnSubmit: (value, ctx) => value,
   effect: {
     title: syncVariableTitle,
     outputs: provideJsonSchemaOutputs,

+ 2 - 1
packages/node-engine/form-core/src/form/types/form-meta.types.ts

@@ -5,7 +5,7 @@
 
 import { MaybePromise } from '@flowgram.ai/utils';
 import { FlowNodeEntity } from '@flowgram.ai/document';
-import { PlaygroundContext } from '@flowgram.ai/core';
+import { PlaygroundContext, PluginContext } from '@flowgram.ai/core';
 
 import { type FormItemAbilityMeta } from './form-ability.types';
 
@@ -97,6 +97,7 @@ export interface IFormMeta {
 export interface NodeFormContext {
   node: FlowNodeEntity;
   playgroundContext: PlaygroundContext;
+  clientContext: PluginContext & Record<string, any>;
 }
 
 export interface IFormMetaOptions {

+ 9 - 8
packages/node-engine/form-core/src/node/types.ts

@@ -6,19 +6,20 @@
 import React from 'react';
 
 import { FlowNodeEntity } from '@flowgram.ai/document';
-import { PlaygroundContext, PluginContext } from '@flowgram.ai/core';
 
-export interface NodeContext {
-  node: FlowNodeEntity;
-  playgroundContext: PlaygroundContext;
-  clientContext: PluginContext & Record<string, any>;
-}
+import { NodeFormContext } from '../form';
+
+/**
+ * @deprecated
+ * use `NodeFormContext` instead
+ */
+export type NodeContext = NodeFormContext;
 
 export type Render<T = any> = (props: T) => any;
 
-export type NodePluginRender = Render<NodeContext>;
+export type NodePluginRender = Render<NodeFormContext>;
 
-export type NodePlaceholderRender = Render<NodeContext>;
+export type NodePlaceholderRender = Render<NodeFormContext>;
 
 export interface NodeRenderProps {
   node: FlowNodeEntity;

+ 16 - 1
packages/node-engine/form/src/react/form.tsx

@@ -31,6 +31,15 @@ export type FormProps<TValues> = FormOptions & {
   control?: FormControl<TValues>;
 };
 
+/**
+ * `FormContentRender` allows you to write `useWatch` to `formMeta.render`
+ */
+function FormContentRender(
+  props: { render: (props: FormRenderProps<any>) => React.ReactNode } & FormRenderProps<any>
+): JSX.Element {
+  const { form, render } = props;
+  return <>{render({ form })}</>;
+}
 /**
  * Hoc That init and provide Form instance. You can also provide form instance from outside by using control prop
  * @param props
@@ -56,7 +65,13 @@ export function Form<TValues>(props: FormProps<TValues>) {
 
   return (
     <FormModelContext.Provider value={formModel}>
-      {children ? (isFunction(children) ? children({ form }) : Children.only(children)) : null}
+      {children ? (
+        isFunction(children) ? (
+          <FormContentRender form={form} render={children} />
+        ) : (
+          Children.only(children)
+        )
+      ) : null}
     </FormModelContext.Provider>
   );
 }

+ 2 - 1
packages/node-engine/node/src/form-model-v2.ts

@@ -13,6 +13,7 @@ import {
   FormModel,
   FormModelValid,
   IFormItem,
+  NodeFormContext,
   OnFormValuesChangePayload,
 } from '@flowgram.ai/form-core';
 import {
@@ -173,7 +174,7 @@ export class FormModelV2 extends FormModel implements Disposable {
     return this._initialized;
   }
 
-  get nodeContext() {
+  get nodeContext(): NodeFormContext {
     return {
       node: this.node,
       playgroundContext: this.node.getService(PlaygroundContext),

+ 2 - 3
packages/node-engine/node/src/form-plugin.ts

@@ -58,11 +58,10 @@ export class FormPlugin<Opts = any> implements Disposable {
     return this._formModel;
   }
 
-  get ctx() {
+  get ctx(): { formModel: FormModelV2 } & NodeFormContext {
     return {
       formModel: this.formModel,
-      node: this.formModel.nodeContext.node,
-      playgroundContext: this.formModel.nodeContext.playgroundContext,
+      ...this.formModel.nodeContext,
     };
   }
 

+ 1 - 8
packages/node-engine/node/src/types.ts

@@ -5,7 +5,7 @@
 
 import * as React from 'react';
 
-import { FormModel, IFormMeta, NodeFormContext } from '@flowgram.ai/form-core';
+import { FormModel, IFormMeta, NodeContext } from '@flowgram.ai/form-core';
 import { FieldName, FieldValue } from '@flowgram.ai/form/src/types';
 import {
   FormRenderProps,
@@ -21,13 +21,6 @@ export interface Node {}
 
 export interface Flow {}
 
-/**
- * NodeContext contains
- * - node: the Editor's node entity.
- * - playgroundContext: the Editor's playgroundContext injected when initiate the Editor.
- */
-type NodeContext = NodeFormContext;
-
 export type Validate<TFieldValue = any, TFormValues = any> = (props: {
   value: TFieldValue;
   formValues: TFormValues;