cherry-pick: Action组件required属性不生效问题 #4560 (#4570)

This commit is contained in:
RUNZE LU 2022-06-09 17:17:08 +08:00 committed by GitHub
parent e1af793147
commit 197682b2e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 100 additions and 74 deletions

View File

@ -960,7 +960,12 @@ export default class Form extends React.Component<FormProps, object> {
data = store.data; data = store.data;
} }
if (Array.isArray(action.required) && action.required.length) { if (Array.isArray(action.required) && action.required.length) {
return store.validateFields(action.required).then(async result => { const fields = action.required.map(item => ({
name: item,
rules: {isRequired: true}
}));
return store.validateFields(fields).then(async result => {
if (!result) { if (!result) {
const dispatcher = await dispatchEvent( const dispatcher = await dispatchEvent(
'validateError', 'validateError',

View File

@ -17,6 +17,7 @@ import {
} from '../utils/helper'; } from '../utils/helper';
import isEqual from 'lodash/isEqual'; import isEqual from 'lodash/isEqual';
import flatten from 'lodash/flatten'; import flatten from 'lodash/flatten';
import find from 'lodash/find';
import {filter} from '../utils/tpl'; import {filter} from '../utils/tpl';
import {normalizeApiResponseData} from '../utils/api'; import {normalizeApiResponseData} from '../utils/api';
@ -537,20 +538,27 @@ export const FormStore = ServiceStore.named('FormStore')
return self.valid; return self.valid;
}); });
const validateFields: (fields: Array<string>) => Promise<boolean> = flow( const validateFields: (
function* validateFields(fields: Array<string>) { fields: Array<string | {name: string; rules: {[propName: string]: any}}>
const items = self.items.concat(); ) => Promise<boolean> = flow(function* validateFields(
let result: Array<boolean> = []; fields: Array<string | {name: string; rules: {[propName: string]: any}}>
for (let i = 0, len = items.length; i < len; i++) { ) {
let item = items[i] as IFormItemStore; const items = self.items.concat();
const normalizedfields = fields.map(field =>
typeof field === 'string' ? {name: field, rules: {}} : field
);
let result: Array<boolean> = [];
if (~fields.indexOf(item.name)) { for (let i = 0, len = items.length; i < len; i++) {
result.push(yield item.validate(self.data)); let item = items[i] as IFormItemStore;
} const field = find(normalizedfields, field => field.name === item.name);
if (field) {
result.push(yield item.validate(self.data, undefined, field.rules));
} }
return result.every(item => item);
} }
); return result.every(item => item);
});
function clearErrors() { function clearErrors() {
const items = self.items.concat(); const items = self.items.concat();

View File

@ -317,70 +317,83 @@ export const FormItemStore = StoreNode.named('FormItemStore')
} }
let validateCancel: Function | null = null; let validateCancel: Function | null = null;
const validate: (data: Object, hook?: any) => Promise<boolean> = flow( const validate: (
function* validate(data: Object, hook?: any) { data: Object,
if (self.validating && !isEffectiveApi(self.validateApi, data)) { hook?: any,
return self.valid; /**
} * customRules主要是为了支持action.require的验证方式
* action实现不同的校验规则
self.validating = true; */
clearError(); customRules?: {[propName: string]: any}
if (hook) { ) => Promise<boolean> = flow(function* validate(
yield hook(); data: Object,
} hook?: any,
customRules?: {[propName: string]: any}
addError( ) {
doValidate(self.tmpValue, data, self.rules, self.messages, self.__) if (self.validating && !isEffectiveApi(self.validateApi, data)) {
);
if (!self.errors.length && isEffectiveApi(self.validateApi, data)) {
if (validateCancel) {
validateCancel();
validateCancel = null;
}
const json: Payload = yield getEnv(self).fetcher(
self.validateApi,
/** 如果配置validateApi需要将用户最新输入同步到数据域内 */
createObject(data, {[self.name]: self.tmpValue}),
{
cancelExecutor: (executor: Function) =>
(validateCancel = executor)
}
);
validateCancel = null;
if (!json.ok && json.status === 422 && json.errors) {
addError(
String(
json.errors || json.msg || `表单项「${self.name}」校验失败`
)
);
}
}
self.validated = true;
if (self.unique && self.form?.parentStore?.storeType === 'ComboStore') {
const combo = self.form.parentStore as IComboStore;
const group = combo.uniques.get(self.name) as IUniqueGroup;
if (
group.items.some(
item =>
item !== self &&
self.tmpValue !== undefined &&
item.value === self.tmpValue
)
) {
addError(self.__('Form.unique'));
}
}
self.validating = false;
return self.valid; return self.valid;
} }
);
self.validating = true;
clearError();
if (hook) {
yield hook();
}
addError(
doValidate(
self.tmpValue,
data,
customRules ? str2rules(customRules) : self.rules,
self.messages,
self.__
)
);
if (!self.errors.length && isEffectiveApi(self.validateApi, data)) {
if (validateCancel) {
validateCancel();
validateCancel = null;
}
const json: Payload = yield getEnv(self).fetcher(
self.validateApi,
/** 如果配置validateApi需要将用户最新输入同步到数据域内 */
createObject(data, {[self.name]: self.tmpValue}),
{
cancelExecutor: (executor: Function) => (validateCancel = executor)
}
);
validateCancel = null;
if (!json.ok && json.status === 422 && json.errors) {
addError(
String(json.errors || json.msg || `表单项「${self.name}」校验失败`)
);
}
}
self.validated = true;
if (self.unique && self.form?.parentStore?.storeType === 'ComboStore') {
const combo = self.form.parentStore as IComboStore;
const group = combo.uniques.get(self.name) as IUniqueGroup;
if (
group.items.some(
item =>
item !== self &&
self.tmpValue !== undefined &&
item.value === self.tmpValue
)
) {
addError(self.__('Form.unique'));
}
}
self.validating = false;
return self.valid;
});
function setError(msg: string | Array<string>, tag: string = 'builtin') { function setError(msg: string | Array<string>, tag: string = 'builtin') {
clearError(); clearError();