diff --git a/src/field/index.js b/src/field/index.js index ace306953..fb3d988b6 100644 --- a/src/field/index.js +++ b/src/field/index.js @@ -80,13 +80,13 @@ export default createComponent({ this.$nextTick(this.adjustSize); if (this.vanForm) { - this.vanForm.fields.push(this); + this.vanForm.addField(this); } }, beforeDestroy() { if (this.vanForm) { - this.vanForm.fields = this.vanForm.fields.filter(item => item !== this); + this.vanForm.removeField(this); } }, diff --git a/src/form/index.js b/src/form/index.js index 980343ad5..2259f5ef8 100644 --- a/src/form/index.js +++ b/src/form/index.js @@ -1,4 +1,5 @@ import { createNamespace } from '../utils'; +import { sortChildren } from '../utils/vnodes'; const [createComponent, bem] = createNamespace('form'); @@ -124,6 +125,15 @@ export default createComponent({ }); }, + addField(field) { + this.fields.push(field); + sortChildren(this.fields, this); + }, + + removeField(field) { + this.fields = this.fields.filter(item => item !== field); + }, + getValues() { return this.fields.reduce((form, field) => { form[field.name] = field.formValue; diff --git a/src/form/test/index.spec.js b/src/form/test/index.spec.js index 47ff652b7..4e97428d7 100644 --- a/src/form/test/index.spec.js +++ b/src/form/test/index.spec.js @@ -35,3 +35,41 @@ test('dynamic add/remove fileds', async () => { await submitForm(wrapper); expect(onSubmit).toHaveBeenCalledWith({ B: '' }); }); + +test('dynamic add fileds when validate-first', async () => { + const onFailed = jest.fn(); + const wrapper = mountForm({ + template: ` + + + + + + `, + data() { + return { + show: false, + }; + }, + methods: { + onFailed, + }, + }); + + await submitForm(wrapper); + expect(onFailed.mock.calls[0][0].errors[0].name).toEqual('B'); + + wrapper.setData({ show: true }); + + await submitForm(wrapper); + expect(onFailed.mock.calls[1][0].errors[0].name).toEqual('A'); +}); diff --git a/src/mixins/relation.ts b/src/mixins/relation.ts index 64830b927..3c0ad74eb 100644 --- a/src/mixins/relation.ts +++ b/src/mixins/relation.ts @@ -1,26 +1,10 @@ -import Vue, { VNode } from 'vue'; +import Vue from 'vue'; +import { sortChildren } from '../utils/vnodes'; type ChildrenMixinOptions = { indexKey?: any; }; -function flattenVNodes(vnodes: VNode[]) { - const result: VNode[] = []; - - function traverse(vnodes: VNode[]) { - vnodes.forEach(vnode => { - result.push(vnode); - - if (vnode.children) { - traverse(vnode.children); - } - }); - } - - traverse(vnodes); - return result; -} - type ChildrenMixinThis = { disableBindRelation?: boolean; }; @@ -72,10 +56,8 @@ export function ChildrenMixin( } const children = [...this.parent.children, this]; - const vnodes = flattenVNodes(this.parent.slots()); - children.sort( - (a, b) => vnodes.indexOf(a.$vnode) - vnodes.indexOf(b.$vnode) - ); + + sortChildren(children, this.parent); this.parent.children = children; }, diff --git a/src/utils/vnodes.ts b/src/utils/vnodes.ts new file mode 100644 index 000000000..89856da3b --- /dev/null +++ b/src/utils/vnodes.ts @@ -0,0 +1,25 @@ +/* eslint-disable no-underscore-dangle */ +import { VNode } from 'vue'; + +function flattenVNodes(vnodes: VNode[]) { + const result: VNode[] = []; + + function traverse(vnodes: VNode[]) { + vnodes.forEach(vnode => { + result.push(vnode); + + if (vnode.children) { + traverse(vnode.children); + } + }); + } + + traverse(vnodes); + return result; +} + +// sort children instances by vnodes order +export function sortChildren(children: any[], parent: any) { + const vnodes = flattenVNodes(parent._vnode.children); + children.sort((a, b) => vnodes.indexOf(a.$vnode) - vnodes.indexOf(b.$vnode)); +}