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