Skip to content

Commit ee6d489

Browse files
committed
fix: formItem error repeat show, close #5349
1 parent c69cf76 commit ee6d489

File tree

3 files changed

+40
-12
lines changed

3 files changed

+40
-12
lines changed

components/form/FormItem.tsx

+20-9
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import FormItemLabel from './FormItemLabel';
3434
import FormItemInput from './FormItemInput';
3535
import type { ValidationRule } from './Form';
3636
import { useProvideFormItemContext } from './FormItemContext';
37+
import useDebounce from './utils/useDebounce';
3738

3839
const ValidateStatuses = tuple('success', 'warning', 'error', 'validating', '');
3940
export type ValidateStatus = typeof ValidateStatuses[number];
@@ -368,15 +369,24 @@ export default defineComponent({
368369
onBeforeUnmount(() => {
369370
formContext.removeField(eventKey);
370371
});
372+
const debounceErrors = useDebounce(errors);
373+
const mergedValidateStatus = computed(() => {
374+
if (props.validateStatus !== undefined) {
375+
return props.validateStatus;
376+
} else if (debounceErrors.value.length) {
377+
return 'error';
378+
}
379+
return validateState.value;
380+
});
371381
const itemClassName = computed(() => ({
372382
[`${prefixCls.value}-item`]: true,
373383

374384
// Status
375-
[`${prefixCls.value}-item-has-feedback`]: validateState.value && props.hasFeedback,
376-
[`${prefixCls.value}-item-has-success`]: validateState.value === 'success',
377-
[`${prefixCls.value}-item-has-warning`]: validateState.value === 'warning',
378-
[`${prefixCls.value}-item-has-error`]: validateState.value === 'error',
379-
[`${prefixCls.value}-item-is-validating`]: validateState.value === 'validating',
385+
[`${prefixCls.value}-item-has-feedback`]: mergedValidateStatus.value && props.hasFeedback,
386+
[`${prefixCls.value}-item-has-success`]: mergedValidateStatus.value === 'success',
387+
[`${prefixCls.value}-item-has-warning`]: mergedValidateStatus.value === 'warning',
388+
[`${prefixCls.value}-item-has-error`]: mergedValidateStatus.value === 'error',
389+
[`${prefixCls.value}-item-is-validating`]: mergedValidateStatus.value === 'validating',
380390
[`${prefixCls.value}-item-hidden`]: props.hidden,
381391
}));
382392
return () => {
@@ -387,7 +397,7 @@ export default defineComponent({
387397
{...attrs}
388398
class={[
389399
itemClassName.value,
390-
(help !== undefined && help !== null) || errors.value.length
400+
(help !== undefined && help !== null) || debounceErrors.value.length
391401
? `${prefixCls.value}-item-with-help`
392402
: '',
393403
attrs.class,
@@ -409,10 +419,11 @@ export default defineComponent({
409419
{/* Input Group */}
410420
<FormItemInput
411421
{...props}
412-
errors={help !== undefined && help !== null ? toArray(help) : errors.value}
422+
errors={
423+
help !== undefined && help !== null ? toArray(help) : debounceErrors.value
424+
}
413425
prefixCls={prefixCls.value}
414-
status={validateState.value}
415-
validateStatus={validateState.value}
426+
status={mergedValidateStatus.value}
416427
ref={inputRef}
417428
help={help}
418429
extra={props.extra ?? slots.extra?.()}

components/form/FormItemInput.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ const FormItemInput = defineComponent({
4040
'prefixCls',
4141
'errors',
4242
'hasFeedback',
43-
'validateStatus',
4443
'onDomErrorVisibleChange',
4544
'wrapperCol',
4645
'help',
@@ -68,7 +67,7 @@ const FormItemInput = defineComponent({
6867
help = slots.help?.(),
6968
errors = slots.errors?.(),
7069
hasFeedback,
71-
validateStatus,
70+
status,
7271
extra = slots.extra?.(),
7372
} = props;
7473
const baseClassName = `${prefixCls}-item`;
@@ -79,7 +78,7 @@ const FormItemInput = defineComponent({
7978
const className = classNames(`${baseClassName}-control`, mergedWrapperCol.class);
8079

8180
// Should provides additional icon if `hasFeedback`
82-
const IconNode = validateStatus && iconMap[validateStatus];
81+
const IconNode = status && iconMap[status];
8382

8483
return (
8584
<Col

components/form/utils/useDebounce.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { Ref } from 'vue';
2+
import { shallowRef, watchEffect } from 'vue';
3+
4+
export default function useDebounce<T>(value: Ref<T[]>): Ref<T[]> {
5+
const cacheValue = shallowRef(value.value.slice());
6+
let timeout: any = null;
7+
watchEffect(() => {
8+
clearTimeout(timeout);
9+
timeout = setTimeout(
10+
() => {
11+
cacheValue.value = value.value;
12+
},
13+
value.value.length ? 0 : 10,
14+
);
15+
});
16+
17+
return cacheValue;
18+
}

0 commit comments

Comments
 (0)