diff --git a/docs/zh-CN/components/form/index.md b/docs/zh-CN/components/form/index.md index f4b3f948a..15cdbdf5b 100755 --- a/docs/zh-CN/components/form/index.md +++ b/docs/zh-CN/components/form/index.md @@ -1430,19 +1430,511 @@ Form 支持轮询初始化接口,步骤如下: 当前组件会对外派发以下事件,可以通过`onEvent`来监听这些事件,并通过`actions`来配置执行的动作,在`actions`中可以通过`${事件参数名}`或`${event.data.[事件参数名]}`来获取事件产生的数据,详细请查看[事件动作](../../docs/concepts/event-action)。 -| 事件名称 | 事件参数 | 说明 | -| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | -| 事件名称 | 事件参数 | 说明 | -| inited | `responseData: any` 请求的响应数据
`responseStatus: number` 响应状态,0 表示成功
`responseMsg: string`响应消息, `error`表示接口是否成功
`[name]: any` 当前数据域中指定字段的值 | initApi 接口请求完成时触发 | -| change | `event.data: object` 当前表单数据 | 表单值变化时触发 | -| formItemValidateSucc | `event.data: object` 当前表单数据 | 表单项校验成功时触发 | -| formItemValidateError | `event.data: object` 当前表单数据 | 表单项校验失败时触发 | -| validateSucc | `event.data: object` 当前表单数据 | 表单校验成功时触发 | -| validateError | `event.data: object` 当前表单数据 | 表单校验失败时触发 | -| submit | `event.data: object` 当前表单数据 | 点击提交按钮或者触发表单提交动作的时候触发,配置了该事件后将不会触发表单提交时的校验、提交到 api 或者 target 等行为,所有行为需要自己配置 | -| submitSucc | `event.data.result: object` api 远程请求成功后返回的结果数据 | 提交成功时触发 | -| submitFail | `event.data.error: object` api 远程请求失败后返回的错误信息 | 提交失败时触发 | -| asyncApiFinished | `[name]: any` 当前数据域中指定字段的值 | asyncApi 远程请求轮训结束 | +| 事件名称 | 事件参数 | 说明 | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | +| 事件名称 | 事件参数 | 说明 | +| inited | `responseData: any` 请求的响应数据
`responseStatus: number` 响应状态,0 表示成功
`responseMsg: string`响应消息, `error`表示接口是否成功
`[name]: any` 当前数据域中指定字段的值 | initApi 接口请求完成时触发 | +| change | `event.data: object` 当前表单数据 | 表单值变化时触发 | +| formItemValidateSucc | `event.data: object` 当前表单数据 | 表单项校验成功时触发(只有`validateOnChange`为`true`或者点击提交过表单又去修改表单项信息的时候才会触发) | +| formItemValidateError | `event.data: object` 当前表单数据 | 表单项校验失败时触发(只有`validateOnChange`为`true`或者点击提交过表单又去修改表单项信息的时候才会触发) | +| validateSucc | `event.data: object` 当前表单数据 | 表单校验成功时触发 | +| validateError | `event.data: object` 当前表单数据 | 表单校验失败时触发 | +| submit | `event.data: object` 当前表单数据 | 点击提交按钮或者触发表单提交动作的时候触发(配置了该事件后将不会触发表单提交时的校验、提交到 api 或者 target 等行为,所有行为需要自己配置) | +| submitSucc | `event.data.result: object` api 远程请求成功后返回的结果数据 | 提交成功时触发 | +| submitFail | `event.data.error: object` api 远程请求失败后返回的错误信息 | 提交失败时触发 | +| asyncApiFinished | `[name]: any` 当前数据域中指定字段的值 | asyncApi 远程请求轮训结束 | + +### inited + +```schema: scope="body" +[ + { + "type": "form", + "initApi": "/api/mock2/form/initData", + "title": "初始化表单", + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名" + }, + { + "type": "input-text", + "name": "email", + "label": "邮箱" + } + ], + "actions": [], + "onEvent": { + "inited": { + "actions": [ + { + "actionType": "setValue", + "componentId": "init_text", + "args": { + "value": "responseData: ${event.data.responseData|json},responseStatus: ${event.data.responseStatus},responseMsg: ${event.data.responseMsg}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "init_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` + +### change + +```schema: scope="body" +[ + { + "type": "form", + "title": "尝试修改表单项", + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名" + }, + { + "type": "input-text", + "name": "email", + "label": "邮箱" + } + ], + "actions": [], + "onEvent": { + "change": { + "actions": [ + { + "actionType": "setValue", + "componentId": "change_text", + "args": { + "value": "${event.data|json}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "change_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` + +### formItemValidateSucc + +只有`validateOnChange`为`true`或者点击提交过表单又去修改表单项信息的时候才会触发。 + +```schema: scope="body" +[ + { + "type": "form", + "title": "尝试修改表单项", + "api": "/api/mock2/form/saveForm", + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名", + "validateOnChange": true, + "value": "amis" + }, + { + "type": "input-text", + "name": "email", + "label": "邮箱", + "value": "amis@baidu.com", + "validateOnChange": true, + "required": true, + "validations": { + "isEmail": true + } + } + ], + "onEvent": { + "formItemValidateSucc": { + "actions": [ + { + "actionType": "setValue", + "componentId": "formitem_validate_succ_text", + "args": { + "value": "${event.data|json}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "formitem_validate_succ_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` + +### formItemValidateError + +只有`validateOnChange`为`true`或者点击提交过表单又去修改表单项信息的时候才会触发。 + +```schema: scope="body" +[ + { + "type": "form", + "title": "尝试修改表单项email", + "api": "/api/mock2/form/x", + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名", + "value": "amis", + "validateOnChange": true + }, + { + "type": "input-text", + "name": "email", + "label": "邮箱", + "value": "amis", + "validateOnChange": true, + "required": true, + "validations": { + "isEmail": true + } + } + ], + "onEvent": { + "formItemValidateError": { + "actions": [ + { + "actionType": "setValue", + "componentId": "formitem_validate_fail_text", + "args": { + "value": "${event.data|json}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "formitem_validate_fail_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` + +### validateSucc + +```schema: scope="body" +[ + { + "type": "form", + "title": "尝试修改表单项", + "api": "/api/mock2/form/saveForm", + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名", + "value": "amis" + }, + { + "type": "input-text", + "name": "email", + "label": "邮箱", + "value": "amis@baidu.com", + "required": true, + "validations": { + "isEmail": true + } + } + ], + "onEvent": { + "validateSucc": { + "actions": [ + { + "actionType": "setValue", + "componentId": "validate_succ_text", + "args": { + "value": "${event.data|json}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "validate_succ_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` + +### validateError + +```schema: scope="body" +[ + { + "type": "form", + "title": "尝试修改表单项", + "api": "/api/mock2/form/x", + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名", + "value": "amis" + }, + { + "type": "input-text", + "name": "email", + "label": "邮箱", + "value": "amis", + "required": true, + "validations": { + "isEmail": true + } + } + ], + "onEvent": { + "validateError": { + "actions": [ + { + "actionType": "setValue", + "componentId": "validate_fail_text", + "args": { + "value": "${event.data|json}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "validate_fail_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` + +### submit + +```schema: scope="body" +[ + { + "type": "form", + "title": "尝试提交表单", + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名", + "value": "amis" + }, + { + "type": "input-text", + "name": "email", + "label": "邮箱", + "value": "amis@baidu.com" + } + ], + "onEvent": { + "submit": { + "actions": [ + { + "actionType": "setValue", + "componentId": "submit_text", + "args": { + "value": "${event.data|json}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "submit_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` + +### submitSucc + +```schema: scope="body" +[ + { + "type": "form", + "title": "尝试提交表单", + "api": "/api/mock2/form/saveForm", + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名", + "value": "amis" + }, + { + "type": "input-text", + "name": "email", + "label": "邮箱", + "value": "amis@baidu.com" + } + ], + "onEvent": { + "submitSucc": { + "actions": [ + { + "actionType": "setValue", + "componentId": "submit_succ_text", + "args": { + "value": "${event.data.result|json}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "submit_succ_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` + +### submitFail + +```schema: scope="body" +[ + { + "type": "form", + "title": "尝试提交表单", + "api": "/api/mock2/form/x", + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名", + "value": "amis" + }, + { + "type": "input-text", + "name": "email", + "label": "邮箱", + "value": "amis@baidu.com" + } + ], + "onEvent": { + "submitFail": { + "actions": [ + { + "actionType": "setValue", + "componentId": "submit_fail_text", + "args": { + "value": "${event.data.error|json}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "submit_fail_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` + +### asyncApiFinished + +```schema: scope="body" +[ + { + "type": "form", + "title": "尝试提交表单", + "api": "/api/mock2/form/saveForm", + "asyncApi": { + "url": "/api/mock2/page/initData", + "mockResponse": { + "status": 200, + "data": { + "status": 0, + "msg": 'ok', + "data": { + id: 2, + finished: true + } + } + } + }, + "body": [ + { + "type": "input-text", + "name": "name", + "label": "姓名" + }, + { + "type": "input-email", + "name": "email", + "label": "邮箱" + } + ], + "onEvent": { + "asyncApiFinished": { + "actions": [ + { + "actionType": "setValue", + "componentId": "async_finished_text", + "args": { + "value": "${event.data|json}" + } + } + ] + } + } + }, + { + "type": "input-text", + "id": "async_finished_text", + "static": true, + "name": "tip", + "label": "上下文" + } +] +``` ## 动作表 diff --git a/packages/amis-core/src/renderers/Form.tsx b/packages/amis-core/src/renderers/Form.tsx index 8aad4aea4..abe19a46a 100644 --- a/packages/amis-core/src/renderers/Form.tsx +++ b/packages/amis-core/src/renderers/Form.tsx @@ -641,7 +641,6 @@ export default class Form extends React.Component { ); } }) - .then(this.dispatchInited) .then(this.initInterval) .then(this.onInit); } else { @@ -676,8 +675,8 @@ export default class Form extends React.Component { errorMessage: fetchFailed } ) - .then(this.dispatchInited) - .then(this.initInterval); + .then(this.initInterval) + .then(this.dispatchInited); } } @@ -719,7 +718,7 @@ export default class Form extends React.Component { } // 派发init事件,参数为初始化数据 - await dispatchEvent( + const result = await dispatchEvent( 'inited', createObject(data, { ...value?.data, // 保留,兼容历史 @@ -729,7 +728,7 @@ export default class Form extends React.Component { }) ); - return value; + return result; } blockRouting(): any { @@ -805,6 +804,15 @@ export default class Form extends React.Component { } onInit && onInit(data, this.props); + + // 派发初始化事件 + const dispatch = await this.dispatchInited({data}); + + if (dispatch?.prevented) { + return; + } + + // submitOnInit submitOnInit && this.handleAction( undefined, @@ -838,8 +846,10 @@ export default class Form extends React.Component { [initFinishedField || 'finished']: false }); + let result: Payload | undefined = undefined; + if (isEffectiveApi(initApi, store.data)) { - const result: Payload = await store.fetchInitData(initApi, store.data, { + result = await store.fetchInitData(initApi, store.data, { successMessage: fetchSuccess, errorMessage: fetchFailed, silent, @@ -861,9 +871,6 @@ export default class Form extends React.Component { } }); - // 派发初始化接口请求完成事件 - await this.dispatchInited(result); - if (result?.ok) { this.initInterval(result); store.reset(undefined, false); @@ -871,6 +878,9 @@ export default class Form extends React.Component { } else { store.reset(undefined, false); } + + // 派发初始化接口请求完成事件 + this.dispatchInited(result); } receive(values: object, name?: string, replace?: boolean) { diff --git a/packages/amis-core/src/renderers/wrapControl.tsx b/packages/amis-core/src/renderers/wrapControl.tsx index 7647039e2..b013d362d 100644 --- a/packages/amis-core/src/renderers/wrapControl.tsx +++ b/packages/amis-core/src/renderers/wrapControl.tsx @@ -629,9 +629,9 @@ export function wrapControl< } const valid = !result.some(item => item === false); - formItemDispatchEvent?.( + (formItemDispatchEvent ?? this.props.dispatchEvent)?.( valid ? 'formItemValidateSucc' : 'formItemValidateError', - data + form?.data ?? this.props.data // form里的一定是最新的数据 ); return valid; }