Преглед изворни кода

fix(form): setValueIn support set undefined value with unknown key (#673)

* fix(form): setValueIn support set undefined value with unknown key

* chore: remove form draft files
xiamidaxia пре 5 месеци
родитељ
комит
2018a4002a

+ 7 - 0
packages/node-engine/form/__tests__/object.test.ts

@@ -202,6 +202,13 @@ describe('object', () => {
       expect(obj).toEqual({ x: [{ y: true }] });
       expect(newObj).toEqual({ x: [{ y: { z: true } }] });
     });
+    it('set undefined value with unknown key', () => {
+      const obj = { a: '' };
+      let newObj = shallowSetIn(obj, 'a', undefined);
+      newObj = shallowSetIn(newObj, 'b', undefined);
+      expect(obj).toEqual({ a: '' });
+      expect(newObj).toEqual({ a: undefined, b: undefined });
+    });
   });
 
   describe('isPromise', () => {

+ 0 - 306
packages/node-engine/form/src/draft/使用方式

@@ -1,306 +0,0 @@
-__________顶层写法__________
-
-export const NodeContainer = ({ node }) => (
-  <NodeProvider>
-    <NodeRender node={node} />
-  </NodeProvider>
-);
-
-
-__________注册Node___________
-
-const LLMNodeRegistry = {
-  type: 'llm'
-  ...
-
-  formMeta: {
-    render: LLMNodeContent
-    options:{
-        formatOnInit...
-    }
-  }
-}
-
-_________简单例子___________
-
-interface FormData {
-    model: string;
-    prompt: string;
-}
-
-const  LLMNodeContent = () => {
-    return(
-        <Form<FormData>>
-            <Field name='model' validators=[({value, context})=>'some error'], effects=[{key: 'log', event: 'onChange'}]>
-                <ModelSelect />
-            </Field>
-            <Field name='prompt' validators=['prompt']>
-                <Prompt />
-            </Field>
-        </Form>
-    )
-}
-
-_________显隐联动___________
-
-interface FormData {
-    isBatch: boolean;
-    batchConfig?: {
-        ...
-    }
-}
-
-const  LLMNodeContent = () => {
-    const form = useForm()
-    return(
-        <Form<FormData>>
-            <Field name='isBatch'>
-                <BatchModeSwitch />
-            </Field>
-            <Field name='batchConfig' deps=['isBatch'] render={也可以将children写在这里}>
-                (props) => form.getValueIn('isBatch') ? <BatchConfig {...props}/>
-            </Field>
-        </Form>
-    )
-}
-
-
-_________UI 数据异构___________
-
-interface FormData {
-    a: string;
-    b: {
-       x: string;
-       y: number;
-    }
-}
-
-const  LLMNodeContent = () => {
-    const form = useForm()
-    return(
-        <Form<FormData>>
-            <Field name='a'>
-                <A />
-            </Field>
-            <Field name='b.x' render={X} />
-            <Field name='b.y' render={({value, onChange})=><Y value={value} onChange={onChange}/>} />
-        </Form>
-    )
-}
-
-_________数组___________
-
-interface FormData {
-    inputs: Array<{name: string; value: string;}>
-}
-
-const  LLMNodeContent = () => {
-    const form = useForm()
-    return(
-        <Form<FormData>>
-            <FieldArray name='inputs' >
-                {
-                    ({ field, formState }) =>
-                        field.map((v, index) =>
-                            <Field name={field.name + '.' + index}>
-                                <MyItem delete={(index)=>field.delete(index)} />
-                            </Field>)
-                }
-                <Add onClick={field.append({name:'x', value: 'abc'})}/>
-            </FieldArray>
-        </Form>
-    )
-}
-
-
-_________校验___________
-
-interface FormData {
-    a: string;
-    b: {
-       x: string;
-    }
-}
-
-const  LLMNodeContent = () => {
-    const form = useForm()
-    return(
-        <Form<FormData>>
-            <Field name='a'>
-                <A />
-            </Field>
-            <Field name='b.x'
-                render={({field, formState})=>{xxx}}
-                rules={[
-                    // 校验器不需要传参,可以直接 string 配置
-                    'not-empty',
-                    // 校验器需要传参
-                    { validator: 'pattern', options: {pattern: '$[0-9]'}},
-                    // 校验器为该节点特化,可以不注册,直接写
-                    { validator: ({value, options, context})=>{xxx}, options: { a:form.values.a }} // 校验联动
-                ]}/>
-        </Form>
-    )
-}
-
-field.isTouched
-
-
-_________effect___________
-
-interface FormData {
-    a: string;
-    b: {
-       x: string;
-    }
-}
-
-const  LLMNodeContent = () => {
-    const form = useForm()
-    return(
-        <Form<FormData>>
-            <Field name='a'>
-                <A />
-            </Field>
-            <Field name='b.x'
-                render={({field})=>{xxx}}
-                effects ={[
-                    {
-                        event: 'onValueChange' // onValueChange, onValueInit, onDispose, 先提供这几个,后续按需扩展
-                        effect: ({event, options, context})=>{...}
-                    }
-                ]}
-        </Form>
-    )
-}
-
-
-____________<Field />__________
-
-- name
-- render
-- rules
-- effects
-
-____________Field______________
-
-
-- name
-- value
-- onChange
-- onFocus
-- onBlur
-- trigger // 触发校验
-- state: FieldState
-
-
-____________ArrayField______________
-
-
-- name
-- value
-- onChange
-- onFocus
-- onBlur
-- trigger // 触发校验
-- state: FieldState
-
-- map
-- append
-- remove
-
-(一期不实现)
-- prepend
-- insert
-- update
-- move
-- swap
-
-____________hooks_____________
-
-- useForm
-- useFormState
-- useField
-- useFieldState
-- useArrayField
-- useTrigger
-
-____________FieldState____________
-- invalid: boolean;
-- isTouched: boolean; // 是否被修改过至少次
-- isDirty: boolean;  // 是否和初始值不同
-- isValidating: boolean;
-- error?: FieldFeedback<Error>;
-- warning?: FieldFeedback<Warning>;
-
-____________FormState_____________
-
-- isDirty: boolean;
-- isLoading: boolean;
-- isSubmitted: boolean;
-- isSubmitSuccessful: boolean;
-- isSubmitting: boolean;
-- isValidating: boolean;
-- invalid: boolean;
-- dirtyFields
-- touchedFields
-- errors?: FieldFeedback<Error>;
-- warnings?: FieldFeedback<Warning>;
-
-
-____________RenderProps__________
-
-- field: Field
-- formState: FormState
-- context: Context
-
-
-____________Context_________________
-
-- 对表单来说context 为给业务层的预留字段
-- 对节点引擎的封装场景来说,节点引擎会注入节点业务context
-
-____________变量集成_____________
-
-
-____________field接口兼容_____________
-
-{
-    value
-    onChange,
-    context: {
-     meta
-     path
-     formModel
-     playgroundContext
-    }
-}
-
-ArrayField {
-   value,
-   onChange,
-   onblur,
-   name,
-   required,
-
-
-
-   add:()=>_inner
-
-
-   private: _innerArrayField
-
-
-   context:{
-
-    node,
-    playground
-   }
-
-}
-
-
-
-
-
-

+ 0 - 122
packages/node-engine/form/src/draft/技术方案

@@ -1,122 +0,0 @@
-___________Store____________
-
-Store  存储表单数据 Values
-
-Values Tree
-
-{
-    f1: {
-        f11:
-        f12:
-    }
-    f2:
-}
-
-
-// 负责数据的增删查改,以及事件
-// 在表单引擎初始化时初始化, 为单例
-Store {
-
-    // 属性
-    - values
-
-    // 方法
-    - getValueIn(path)
-    - getStateIn(path)
-
-    // 事件
-    - onValuesChanged
-}
-
-
-__________Path_____________
-
-Path =  string | string [] | Path
-
-
-
-___________Field_____________
-
-// 表单项内部模型
-FieldModel {
-
-    - name
-    - ref
-
-    - get value
-    - set value
-
-    - state
-    - set state
-
-    - parent: FieldModel[] // 用于事件冒泡
-    - children: FieldModel[]
-
-    - onValueChange
-    - onStateChange
-    - onFocus
-    - onBlur
-
-}
-
-// 表单项对外门面模型
-Field {
-    - name
-    - value
-    - onChange
-    - onFocus
-    - onBlur
-    - validate // 触发校验
-    - state: FieldState
-}
-
-
-__________校验 & effect_____________
-
-// 独立维护校验和effect, 不耦合到FieldModel中
-// 通过事件驱动执行
-
-RulesMap: WeakMap<FieldModel, Rules>
-EffectsMap: WeakMap<FieldModel, Effects>
-
-___________FormModel_______________
-
-// 表单内部模型
-FormModel {
-
-    - context
-    - ref
-    - initialValues
-
-    - get values
-    - set values
-
-    - get states
-    - set states
-
-    - field: FieldModel
-}
-
-// 表单对外门面模型
-Form {
-    - context
-    - initialValues
-
-    - values
-    - state: Proxy<FormState>
-
-    - getValueIn(path)
-    - setValueIn(path)
-
-    // 以下,目前业务没有用到,按需实现
-
-    - setErrorIn
-
-    - reset()
-    - resetField(path)
-
-    - setFocus
-
-}
-
-

+ 2 - 1
packages/node-engine/form/src/utils/object.ts

@@ -81,7 +81,8 @@ export function shallowSetIn(obj: any, path: string, value: any): any {
   }
 
   // Return original object if new value is the same as current
-  if ((i === 0 ? obj : resVal)[pathArray[i]] === value) {
+  //  `pathArray[i] in obj` is to supoort set undefined value with unknown key
+  if ((i === 0 ? obj : resVal)[pathArray[i]] === value && pathArray[i] in obj) {
     return obj;
   }