fix(components): [el-form] clear validate after reset fields

- Enhancement for #6758
- Add test case against changes
This commit is contained in:
JeremyWuuuuu 2022-03-24 17:44:01 +08:00 committed by zouhang
parent f74f4e94d2
commit f2d23ba049
2 changed files with 41 additions and 15 deletions

View File

@ -28,7 +28,7 @@ describe('Form', () => {
installStyle()
})
test('label width', async () => {
it('label width', async () => {
const wrapper = mount({
setup() {
const form = reactive({
@ -46,7 +46,7 @@ describe('Form', () => {
expect(findStyle(wrapper, '.el-form-item__label').width).toBe('80px')
})
test('auto label width', async () => {
it('auto label width', async () => {
const labelPosition = ref('right')
const wrapper = mount({
setup() {
@ -100,7 +100,7 @@ describe('Form', () => {
expect(marginRight).toEqual(marginRight1)
})
test('form-item auto label width', async () => {
it('form-item auto label width', async () => {
const wrapper = mount({
setup() {
const form = reactive({
@ -155,7 +155,7 @@ describe('Form', () => {
expect(labelWidth2).toEqual('auto')
})
test('inline form', () => {
it('inline form', () => {
const wrapper = mount({
setup() {
const form = reactive({
@ -177,7 +177,7 @@ describe('Form', () => {
expect(wrapper.classes()).toContain('el-form--inline')
})
test('label position', () => {
it('label position', () => {
const wrapper = mount({
setup() {
const form = reactive({
@ -214,7 +214,7 @@ describe('Form', () => {
)
})
test('label size', () => {
it('label size', () => {
const wrapper = mount({
setup() {
const form = reactive({
@ -238,7 +238,7 @@ describe('Form', () => {
)
})
test('show message', (done) => {
it('show message', (done) => {
const wrapper = mount({
setup() {
const form = reactive({
@ -277,7 +277,8 @@ describe('Form', () => {
})
})
test('reset field', async () => {
it('reset field', async () => {
jest.useFakeTimers()
const form = reactive({
name: '',
address: '',
@ -333,13 +334,23 @@ describe('Form', () => {
const formRef = wrapper.findComponent({ ref: 'form' }).vm as FormInstance
formRef.resetFields()
// first await waits for the validation to be dispatched.
await rAF()
await nextTick()
// after validation dispatched, it will update `validateStateDebounced` with a 100ms delay.
// That's why we put this `jest.runAllTimers` here.
jest.runAllTimers()
// after timer fired, we should wait for the UI to be updated.
await rAF()
await nextTick()
expect(form.name).toBe('')
expect(form.address).toBe('')
expect(form.type.length).toBe(0)
expect(wrapper.findAll('.el-form-item__error')).toHaveLength(0)
jest.useRealTimers()
})
test('clear validate', async () => {
it('clear validate', async () => {
const wrapper = mount({
setup() {
const form = reactive({
@ -408,7 +419,7 @@ describe('Form', () => {
expect(addressField.validateMessage).toBe('')
})
test('scroll to field', () => {
it('scroll to field', () => {
const wrapper = mount({
setup() {
return () => (
@ -439,7 +450,7 @@ describe('Form', () => {
window.HTMLElement.prototype.scrollIntoView = oldScrollIntoView
})
test('validate return parameters', async () => {
it('validate return parameters', async () => {
const form = reactive({
name: 'test',
age: '',
@ -501,7 +512,7 @@ describe('Form', () => {
expect(res.fields).toBe(undefined)
})
test('validate status', async () => {
it('validate status', async () => {
const form = reactive({
age: '20',
})

View File

@ -44,7 +44,7 @@ import {
useSlots,
} from 'vue'
import AsyncValidator from 'async-validator'
import { clone } from 'lodash-unified'
import { clone, isEqual } from 'lodash-unified'
import { refDebounced } from '@vueuse/core'
import {
addUnit,
@ -89,7 +89,9 @@ const validateState = ref<FormItemValidateState>('')
const validateStateDebounced = refDebounced(validateState, 100)
const validateMessage = ref('')
const formItemRef = ref<HTMLDivElement>()
// special inline value.
let initialValue: any = undefined
let isResettingField = false
const labelStyle = computed<CSSProperties>(() => {
if (formContext.labelPosition === 'top') {
@ -251,6 +253,12 @@ const doValidate = async (rules: RuleItem[]): Promise<true> => {
}
const validate: FormItemContext['validate'] = async (trigger, callback) => {
// skip validation if its resetting
if (isResettingField) {
isResettingField = false
return false
}
const hasCallback = isFunction(callback)
if (!validateEnabled.value) {
callback?.(false)
@ -286,8 +294,15 @@ const resetField: FormItemContext['resetField'] = async () => {
const model = formContext.model
if (!model || !props.prop) return
getProp(model, props.prop).value = initialValue
await nextTick()
const computedValue = getProp(model, props.prop)
if (!isEqual(computedValue.value, initialValue)) {
// prevent validation from being triggered
isResettingField = true
}
computedValue.value = initialValue
await nextTick()
clearValidate()
}