fix: formItem error repeat show, close #5349
parent
c69cf76d3c
commit
ee6d489bf4
|
@ -34,6 +34,7 @@ import FormItemLabel from './FormItemLabel';
|
||||||
import FormItemInput from './FormItemInput';
|
import FormItemInput from './FormItemInput';
|
||||||
import type { ValidationRule } from './Form';
|
import type { ValidationRule } from './Form';
|
||||||
import { useProvideFormItemContext } from './FormItemContext';
|
import { useProvideFormItemContext } from './FormItemContext';
|
||||||
|
import useDebounce from './utils/useDebounce';
|
||||||
|
|
||||||
const ValidateStatuses = tuple('success', 'warning', 'error', 'validating', '');
|
const ValidateStatuses = tuple('success', 'warning', 'error', 'validating', '');
|
||||||
export type ValidateStatus = typeof ValidateStatuses[number];
|
export type ValidateStatus = typeof ValidateStatuses[number];
|
||||||
|
@ -368,15 +369,24 @@ export default defineComponent({
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
formContext.removeField(eventKey);
|
formContext.removeField(eventKey);
|
||||||
});
|
});
|
||||||
|
const debounceErrors = useDebounce(errors);
|
||||||
|
const mergedValidateStatus = computed(() => {
|
||||||
|
if (props.validateStatus !== undefined) {
|
||||||
|
return props.validateStatus;
|
||||||
|
} else if (debounceErrors.value.length) {
|
||||||
|
return 'error';
|
||||||
|
}
|
||||||
|
return validateState.value;
|
||||||
|
});
|
||||||
const itemClassName = computed(() => ({
|
const itemClassName = computed(() => ({
|
||||||
[`${prefixCls.value}-item`]: true,
|
[`${prefixCls.value}-item`]: true,
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
[`${prefixCls.value}-item-has-feedback`]: validateState.value && props.hasFeedback,
|
[`${prefixCls.value}-item-has-feedback`]: mergedValidateStatus.value && props.hasFeedback,
|
||||||
[`${prefixCls.value}-item-has-success`]: validateState.value === 'success',
|
[`${prefixCls.value}-item-has-success`]: mergedValidateStatus.value === 'success',
|
||||||
[`${prefixCls.value}-item-has-warning`]: validateState.value === 'warning',
|
[`${prefixCls.value}-item-has-warning`]: mergedValidateStatus.value === 'warning',
|
||||||
[`${prefixCls.value}-item-has-error`]: validateState.value === 'error',
|
[`${prefixCls.value}-item-has-error`]: mergedValidateStatus.value === 'error',
|
||||||
[`${prefixCls.value}-item-is-validating`]: validateState.value === 'validating',
|
[`${prefixCls.value}-item-is-validating`]: mergedValidateStatus.value === 'validating',
|
||||||
[`${prefixCls.value}-item-hidden`]: props.hidden,
|
[`${prefixCls.value}-item-hidden`]: props.hidden,
|
||||||
}));
|
}));
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -387,7 +397,7 @@ export default defineComponent({
|
||||||
{...attrs}
|
{...attrs}
|
||||||
class={[
|
class={[
|
||||||
itemClassName.value,
|
itemClassName.value,
|
||||||
(help !== undefined && help !== null) || errors.value.length
|
(help !== undefined && help !== null) || debounceErrors.value.length
|
||||||
? `${prefixCls.value}-item-with-help`
|
? `${prefixCls.value}-item-with-help`
|
||||||
: '',
|
: '',
|
||||||
attrs.class,
|
attrs.class,
|
||||||
|
@ -409,10 +419,11 @@ export default defineComponent({
|
||||||
{/* Input Group */}
|
{/* Input Group */}
|
||||||
<FormItemInput
|
<FormItemInput
|
||||||
{...props}
|
{...props}
|
||||||
errors={help !== undefined && help !== null ? toArray(help) : errors.value}
|
errors={
|
||||||
|
help !== undefined && help !== null ? toArray(help) : debounceErrors.value
|
||||||
|
}
|
||||||
prefixCls={prefixCls.value}
|
prefixCls={prefixCls.value}
|
||||||
status={validateState.value}
|
status={mergedValidateStatus.value}
|
||||||
validateStatus={validateState.value}
|
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
help={help}
|
help={help}
|
||||||
extra={props.extra ?? slots.extra?.()}
|
extra={props.extra ?? slots.extra?.()}
|
||||||
|
|
|
@ -40,7 +40,6 @@ const FormItemInput = defineComponent({
|
||||||
'prefixCls',
|
'prefixCls',
|
||||||
'errors',
|
'errors',
|
||||||
'hasFeedback',
|
'hasFeedback',
|
||||||
'validateStatus',
|
|
||||||
'onDomErrorVisibleChange',
|
'onDomErrorVisibleChange',
|
||||||
'wrapperCol',
|
'wrapperCol',
|
||||||
'help',
|
'help',
|
||||||
|
@ -68,7 +67,7 @@ const FormItemInput = defineComponent({
|
||||||
help = slots.help?.(),
|
help = slots.help?.(),
|
||||||
errors = slots.errors?.(),
|
errors = slots.errors?.(),
|
||||||
hasFeedback,
|
hasFeedback,
|
||||||
validateStatus,
|
status,
|
||||||
extra = slots.extra?.(),
|
extra = slots.extra?.(),
|
||||||
} = props;
|
} = props;
|
||||||
const baseClassName = `${prefixCls}-item`;
|
const baseClassName = `${prefixCls}-item`;
|
||||||
|
@ -79,7 +78,7 @@ const FormItemInput = defineComponent({
|
||||||
const className = classNames(`${baseClassName}-control`, mergedWrapperCol.class);
|
const className = classNames(`${baseClassName}-control`, mergedWrapperCol.class);
|
||||||
|
|
||||||
// Should provides additional icon if `hasFeedback`
|
// Should provides additional icon if `hasFeedback`
|
||||||
const IconNode = validateStatus && iconMap[validateStatus];
|
const IconNode = status && iconMap[status];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col
|
<Col
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
import { shallowRef, watchEffect } from 'vue';
|
||||||
|
|
||||||
|
export default function useDebounce<T>(value: Ref<T[]>): Ref<T[]> {
|
||||||
|
const cacheValue = shallowRef(value.value.slice());
|
||||||
|
let timeout: any = null;
|
||||||
|
watchEffect(() => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(
|
||||||
|
() => {
|
||||||
|
cacheValue.value = value.value;
|
||||||
|
},
|
||||||
|
value.value.length ? 0 : 10,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return cacheValue;
|
||||||
|
}
|
Loading…
Reference in New Issue