diff --git a/example/src/forms/network/form.tsx b/example/src/forms/network/form.tsx
index 012c9ae..3c43b81 100644
--- a/example/src/forms/network/form.tsx
+++ b/example/src/forms/network/form.tsx
@@ -23,7 +23,7 @@ const Network = createForm({
},
interface: {
value: "wifi",
- title: 1,//"网卡类型",
+ title: "网卡类型",
enable: true,
select: () => {
return [
@@ -103,7 +103,7 @@ const Network = createForm({
submit: { // 这是一个动作,
title: "提交wifi",
enable: (net: any) => net.interface.value === "wifi",
- validate: (value: string) => value.length > 6,
+ // validate: (value: string) => value.length > 6,
execute:async (wifi:any)=>{
await delay(2000)
console.log("提交wifi=",wifi)
@@ -145,9 +145,6 @@ const Network = createForm({
},
progressSubmit2: { // 这是一个动作,
title: "提交进度2",
- validate:async ()=>{
- return true
- },
execute:action(async (fields,{getProgressbar})=>{
console.log("submit fields=",fields)
const bar = getProgressbar()
@@ -214,24 +211,23 @@ const Network = createForm({
},
timeoutSubmit: {
title: "提交超时倒计时",
- execute: computed(async () => {
+ execute: computed(async (scope: Dict) => {
+ console.log("ping=",Object.assign({},scope));
await delay(5000);
},[],{timeout:2000}),
},
ping: {
title: "测试网络连通性",
- scope:"fields.wifi",
enable: computed((wifi: any) => {
return wifi.ssid.value.length > 0
},{scope:"fields.wifi"}),
execute: async (a: Dict) => {
- await delay(2000);
- console.log(a);
+ await delay(1000);
+ console.log("ping=",Object.assign({},a));
},
},
// 向导表单:上一步
previous:{
-
enable: (wifi: any) => wifi.ssid.value.length > 0,
execute:async ()=>{
return 1
diff --git a/example/src/forms/network/index.tsx b/example/src/forms/network/index.tsx
index 04d6da3..a2678bd 100644
--- a/example/src/forms/network/index.tsx
+++ b/example/src/forms/network/index.tsx
@@ -90,6 +90,11 @@ const NetworkForm = ()=>{
return
}}
+ name="fields.wifi.standardSubmit" >
+ {({title,visible,loading,enable,run,timeout})=>{
+ return
+ }}
+
name="fields.wifi.timeoutSubmit" >
{({title,visible,loading,enable,run,error,timeout})=>{
return
diff --git a/packages/core/src/action.tsx b/packages/core/src/action.tsx
index 0c6d333..671e3ae 100644
--- a/packages/core/src/action.tsx
+++ b/packages/core/src/action.tsx
@@ -34,7 +34,7 @@
import { ReactNode, useCallback, useRef, RefObject,useState} from "react";
import React from "react";
import type { FormDefine, FormStore } from "./form";
-import { AsyncComputedDefine, AsyncComputedGetter, AsyncComputedObject, ComputedDescriptorDefine, ComputedOptions, ComputedParams, Dict, RuntimeComputedOptions, computed, getValueByPath} from '@speedform/reactive';
+import { AsyncComputedDefine, AsyncComputedGetter, AsyncComputedObject, ComputedDescriptorDefine, ComputedOptions, ComputedParams, Dict, RuntimeComputedOptions, computed, getVal, getValueByPath} from '@speedform/reactive';
import { omit } from "flex-tools/object/omit";
import { getFormData } from "./serialize";
import { getId } from "./utils";
@@ -357,6 +357,8 @@ export function createUseAction(store:For
execute:action(executor,options)
}
})
+ // 读取一次以触发计算属性对象的创建
+ getValueByPath(state,['actions',actionName])
}
ref.current = actionName
}
diff --git a/packages/core/src/form.tsx b/packages/core/src/form.tsx
index c4f1cb4..d061ee5 100644
--- a/packages/core/src/form.tsx
+++ b/packages/core/src/form.tsx
@@ -46,7 +46,7 @@ import { createFieldComponent, FormFields } from './field';
import { createFieldGroupComponent } from "./fieldGroup";
import { assignObject } from "flex-tools/object/assignObject";
import { FormActions, UseActionType, createActionComponent, createUseAction, getAction } from './action';
-import { FIELDS_STATE_KEY, VALIDATE_COMPUTED_GROUP } from './consts';
+import { ACTIONS_STATE_KEY, FIELDS_STATE_KEY, VALIDATE_COMPUTED_GROUP } from './consts';
import { defaultObject } from "flex-tools/object/defaultObject";
import { createObjectProxy } from "./utils";
import { createLoadApi, createGetValuesApi } from "./serialize";
@@ -167,6 +167,21 @@ export type FormStatus = 'idle'
// actions : Actions // 表单动作
// }
+/**
+ * 设置表单默认属性
+ * title?:ComputedAttr // 动作标题
+ help?:ComputedAttr // 动作帮助
+ tips?:ComputedAttr // 动作提示
+ visible?:ComputedAttr // 是否可见
+ enable?:ComputedAttr // 是否可用
+ valid?:ComputedAttr // 是否有效
+ readonly?:ComputedAttr // 是否只读
+ * @param define
+ */
+ function setFormDefault(define:T){
+ return defaultObject(define,defaultFormProps) as typeof defaultFormProps & T
+ }
+
/**
*
@@ -202,21 +217,6 @@ function createValidatorHook(valuePath:string[],options:ComputedOptions){
}
-/**
- * 设置表单默认属性
- * title?:ComputedAttr // 动作标题
- help?:ComputedAttr // 动作帮助
- tips?:ComputedAttr // 动作提示
- visible?:ComputedAttr // 是否可见
- enable?:ComputedAttr // 是否可用
- valid?:ComputedAttr // 是否有效
- readonly?:ComputedAttr // 是否只读
- * @param define
- */
-function setFormDefault(define:T){
- return defaultObject(define,defaultFormProps) as typeof defaultFormProps & T
-}
-
/**
@@ -238,25 +238,29 @@ function setFormDefault(define:T){
*
*/
function createActionHook(valuePath:string[],options:ComputedOptions){
- if(valuePath.length>1 && valuePath[valuePath.length-1]=='execute'){
- // 默认不自动执行,需要手动调用action.execute.run()来执行
- options.immediate = false
- // 如果没有指定scope,则默认指向fields,这样就可以直接使用fields下的字段,而不需要fields前缀
- if(options.scope){
- if(Array.isArray(options.scope)){
- // 如果scope中没有fields,则添加fields,并且保证fields在第一个位置
- if(options.scope.length>0 && options.scope[0]!=FIELDS_STATE_KEY){
- options.scope.unshift(FIELDS_STATE_KEY)
- }
+ if(valuePath.length>1 ){
+ if(valuePath[valuePath.length-1]=='execute'){
+ // 默认不自动执行,需要手动调用action.execute.run()来执行
+ options.immediate = false
+ // 如果没有指定scope,则默认指向fields,这样就可以直接使用fields下的字段,而不需要fields前缀
+ if(options.scope){
+ if(Array.isArray(options.scope)){
+ // 如果scope中没有fields,则添加fields,并且保证fields在第一个位置
+ if(options.scope.length>0 && options.scope[0]!=FIELDS_STATE_KEY){
+ options.scope.unshift(FIELDS_STATE_KEY)
+ }
+ }
+ }else{// 如果没有指定scope,则默认指向fields
+ options.scope = [FIELDS_STATE_KEY]
}
- }else{// 如果没有指定scope,则默认指向fields,
- options.scope = [FIELDS_STATE_KEY]
- }
- options.noReentry = true // 禁止重入
+ options.noReentry = true // 禁止重入
+ }
}
+
}
/**
* 对所有位于fields下的的依赖均自动添加fields前缀,这样在声明依赖时就可以省略fields前缀
+ *
* @param valuePath
* @param getter
* @param options
@@ -273,6 +277,7 @@ function createDepsHook(valuePath:string[],options:ComputedOptions){
}
}
+
/**
*
* 冻结表单,即表单计算函数不再执行
@@ -292,6 +297,27 @@ export function getFieldName(valuePath:string[]){
valuePath.slice(0,-1).join(".") : valuePath.join(".") : ''
}
+export type FormObject = {
+ state: FormState,
+ useState: (fn: (state: FormState) => any) => any,
+ setState: (fn: (draft: FormState) => void) => void,
+ Form: FormComponent,
+ Field: ReactFC,
+ Group: ReactFC,
+ Action: ReactFC,
+ Submit: ReactFC,
+ Reset: ReactFC,
+ useAction: UseActionType,
+ fields: State['fields'],
+ actions: State['actions'],
+ getAction: (name: string) => any,
+ freeze: (value?: boolean) => void,
+ load: (data: Dict) => void,
+ getValues: () => Dict,
+ computedObjects: Dict,
+ watchObjects: Dict,
+ validate: (value?: Dict) => Promise
+}
/**
* 创建声明表单
*
@@ -310,7 +336,8 @@ export function createForm(schema: State,op
// 创建表单Store对象实例
const store = createStore(schema ,{
- debug:opts.debug,
+ debug:opts.debug,
+ immediate:true, // 默认立即执行完成所有计算属性的初始化
// 计算函数作用域默认指向fields
scope: ()=>[FIELDS_STATE_KEY],
// 创建计算函数时的钩子函数,可以在创建前做一些不可描述的处理
@@ -322,15 +349,13 @@ export function createForm(schema: State,op
// 3. 将表单actions的execute的onComputedResult指向其current
createActionHook(valuePath,options)
},
- onComputedDraft(draft,{computedType,valuePath}){
- // 针对计算属性
+ getRootScope(draft,{computedType,valuePath}){
// 修改fields下的所有计算函数的作用域根,使之总是指向fields开头
// 这样可以保证在计算函数中,当scope->Root时,总是指向fields,否则就需要state.fields.xxx.xxx
if(computedType==='Computed' && valuePath.length >0 && valuePath[0]==FIELDS_STATE_KEY){
return draft.fields
}
- },
- immediate:true // 默认立即执行完成所有计算属性的初始化
+ }
});
/**
@@ -370,7 +395,7 @@ export function createForm(schema: State,op
computedObjects: formStore.computedObjects,
watchObjects : formStore.watchObjects,
validate : createValidator(formStore)
- };
+ }
}
@@ -379,55 +404,100 @@ export function createForm(schema: State,op
*
* 当使用标准的表单提交模式时,使用该组件
*
+ * 简单用法:
+ * {
+ * console.log(data)
+ * }}
+ * onLoading={(loading)=>{ }}
+ * onError={(error)=>{}}
+ * onValid={(valid)=>{}}
+ * >
+ *
+ *
+ * 提交
+ *
*
- *