Skip to content

Commit

Permalink
fix(vue): fix field doesnt update correctly in designable mode (#1799)
Browse files Browse the repository at this point in the history
  • Loading branch information
MisicDemone authored Jul 14, 2021
1 parent 5f8c187 commit 837cfc0
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 119 deletions.
5 changes: 3 additions & 2 deletions packages/vue/docs/api/shared/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,10 @@ import { Schema } from '@formily/react'
Schema.registerVoidComponents(['card', 'tab', 'step'])
```

<Alert type="warning">
::: warning

<p>注意,该 api 需要配合 <code>enablePolyfills(['1.0'])</code> 使用</p>
</Alert>
:::

### registerTypeDefaultComponents

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import {
RecursionField,
useField,
useFieldSchema,
observer,
} from '@formily/vue'
import { observer } from '@formily/reactive-vue'
import 'ant-design-vue/dist/antd.css'
const ArrayItems = observer(
Expand Down
71 changes: 38 additions & 33 deletions packages/vue/docs/demos/api/hooks/use-field.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
/>
<FormConsumer>
<template #default="{ form }">
<div style="white-space: pre; margin-bottom: 16px;">{{JSON.stringify(form.values, null, 2)}}</div>
<div style="white-space: pre; margin-bottom: 16px">
{{ JSON.stringify(form.values, null, 2) }}
</div>
<Button
type="primary"
@click="() => {
form.submit(log)
}"
@click="
() => {
form.submit(log)
}
"
>
Submit
</Button>
Expand All @@ -29,55 +33,56 @@
import { defineComponent, h } from '@vue/composition-api'
import { Form, Input, Button } from 'ant-design-vue'
import { createForm, setValidateLanguage } from '@formily/core'
import {
FormProvider,
FormConsumer,
Field,
useField,
observer
} from '@formily/vue'
import { FormProvider, FormConsumer, Field, useField } from '@formily/vue'
import { observer } from '@formily/reactive-vue'
import 'ant-design-vue/dist/antd.css'
setValidateLanguage('en')
const FormItem = observer(defineComponent({
setup (props, { slots }) {
const fieldRef = useField()
return () => {
const field = fieldRef.value
return h(Form.Item, {
props: {
label: field.title,
required: field.required,
help: field.errors?.length ? field.errors : undefined,
extra: field.description,
validateStatus: field.validateStatus,
}
}, slots?.default())
}
}
}))
const FormItem = observer(
defineComponent({
setup(props, { slots }) {
const fieldRef = useField()
return () => {
const field = fieldRef.value
return h(
Form.Item,
{
props: {
label: field.title,
required: field.required,
help: field.errors?.length ? field.errors : undefined,
extra: field.description,
validateStatus: field.validateStatus,
},
},
slots?.default()
)
}
},
})
)
export default {
components: {
FormProvider,
FormConsumer,
Field,
Form,
Button
Button,
},
data() {
const form = createForm({ validateFirst: true })
return {
FormItem,
Input,
form
form,
}
},
methods: {
log (...args) {
log(...args) {
console.log(...args)
}
}
},
},
}
</script>
29 changes: 16 additions & 13 deletions packages/vue/docs/demos/api/hooks/use-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,36 @@
<script>
import { defineComponent, h } from '@vue/composition-api'
import { createForm } from '@formily/core'
import { FormProvider, Field, useForm, observer } from '@formily/vue'
import { FormProvider, Field, useForm } from '@formily/vue'
import { observer } from '@formily/reactive-vue'
import { Input, Space } from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'
const Custom = observer(defineComponent({
setup () {
const formRef = useForm()
return () => {
const form = formRef.value
return h('div', {}, [form.values.input])
}
},
}))
const Custom = observer(
defineComponent({
setup() {
const formRef = useForm()
return () => {
const form = formRef.value
return h('div', {}, [form.values.input])
}
},
})
)
export default {
components: {
FormProvider,
Field,
Space
Space,
},
data() {
const form = createForm({ validateFirst: true })
return {
Input,
Custom,
form
form,
}
}
},
}
</script>
51 changes: 40 additions & 11 deletions packages/vue/src/__tests__/field.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ test('render field', async () => {
const atBlur = jest.fn()
const atFocus = jest.fn()

const { getByTestId, queryByTestId, unmount } = render(
const { getByTestId, queryByTestId } = render(
defineComponent({
name: 'TestComponent',
setup() {
Expand Down Expand Up @@ -140,7 +140,6 @@ test('render field', async () => {
expect(queryByTestId('ee')).toBeNull()
expect(form.query('aa').get('value')).toEqual('123')
expect(form.query('kk').get('value')).toEqual('123')
Vue.nextTick(() => unmount)
})

test('ReactiveField', () => {
Expand All @@ -155,25 +154,55 @@ test('ReactiveField', () => {
})

test('useAttch', async () => {
const form = createForm()
const form1 = createForm()
const MyComponent = defineComponent({
props: ['name'],
props: ['form', 'name1', 'name2', 'name3', 'name4'],
data() {
return { form, Input, Decorator }
return { Input, Decorator }
},
template: `<FormProvider :form="form">
<Field :name="name" :decorator="[Decorator]" :component="[Input]" />
<Field :name="name1" :decorator="[Decorator]" :component="[Input]" />
<ArrayField :name="name2" :decorator="[Decorator]" :component="[Input]" />
<ObjectField :name="name3" :decorator="[Decorator]" :component="[Input]" />
<VoidField :name="name4" :decorator="[Decorator]" :component="[Input]" />
</FormProvider>`,
})
const { updateProps } = render(MyComponent, {
props: {
name: 'aa',
form: form1,
name1: 'aa',
name2: 'bb',
name3: 'cc',
name4: 'dd',
},
})
expect(form.query('aa').take().mounted).toBeTruthy()
await updateProps({ name: 'bb' })
expect(form.query('aa').take().mounted).toBeFalsy()
expect(form.query('bb').take().mounted).toBeTruthy()
expect(form1.mounted).toBeTruthy()
expect(form1.query('aa').take().mounted).toBeTruthy()
expect(form1.query('bb').take().mounted).toBeTruthy()
expect(form1.query('cc').take().mounted).toBeTruthy()
expect(form1.query('dd').take().mounted).toBeTruthy()
await updateProps({
name1: 'aaa',
name2: 'bbb',
name3: 'ccc',
name4: 'ddd',
})
await Vue.nextTick()
expect(form1.query('aa').take().mounted).toBeFalsy()
expect(form1.query('bb').take().mounted).toBeFalsy()
expect(form1.query('cc').take().mounted).toBeFalsy()
expect(form1.query('dd').take().mounted).toBeFalsy()
expect(form1.query('aaa').take().mounted).toBeTruthy()
expect(form1.query('bbb').take().mounted).toBeTruthy()
expect(form1.query('ccc').take().mounted).toBeTruthy()
expect(form1.query('ddd').take().mounted).toBeTruthy()
const form2 = createForm()
await updateProps({
form: form2,
})
await Vue.nextTick()
expect(form1.unmounted).toBeTruthy()
expect(form2.mounted).toBeTruthy()
})

test('useFormEffects', async () => {
Expand Down
29 changes: 19 additions & 10 deletions packages/vue/src/components/ArrayField.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { provide, defineComponent } from 'vue-demi'
import { provide, defineComponent, watch, computed } from 'vue-demi'
import { useField, useForm } from '../hooks'
import { useAttach } from '../hooks/useAttach'
import ReactiveField from './ReactiveField'
Expand Down Expand Up @@ -64,18 +64,27 @@ export default observer(
setup(props: IArrayFieldProps, { slots }) {
const formRef = useForm()
const parentRef = useField()
const basePath =

const basePath = computed(() =>
props.basePath !== undefined
? props.basePath
: parentRef?.value?.address
const fieldRef = useAttach(
() =>
formRef.value.createArrayField({
...props,
basePath,
...getRawComponent(props),
}),
[() => props.name, formRef]
)
const createField = () =>
formRef.value.createArrayField({
...props,
basePath: basePath.value,
...getRawComponent(props),
})
const [fieldRef, checker] = useAttach(createField())
watch(
() => props,
() => (fieldRef.value = checker(createField())),
{ deep: true }
)
watch(
[formRef, parentRef],
() => (fieldRef.value = checker(createField()))
)

provide(FieldSymbol, fieldRef)
Expand Down
24 changes: 14 additions & 10 deletions packages/vue/src/components/Field.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { provide, defineComponent, computed } from 'vue-demi'
import { provide, defineComponent, watch, computed } from 'vue-demi'
import { useField, useForm } from '../hooks'
import { useAttach } from '../hooks/useAttach'
import { FieldSymbol } from '../shared/context'
Expand Down Expand Up @@ -62,19 +62,23 @@ export default defineComponent<IFieldProps>({
setup(props: IFieldProps, { slots }) {
const formRef = useForm()
const parentRef = useField()

const basePath = computed(() =>
props.basePath !== undefined ? props.basePath : parentRef?.value?.address
)

const fieldRef = useAttach(
() =>
formRef.value.createField({
...props,
basePath: basePath.value,
...getRawComponent(props),
}),
[() => props.name, basePath, formRef]
const createField = () =>
formRef.value.createField({
...props,
basePath: basePath.value,
...getRawComponent(props),
})
const [fieldRef, checker] = useAttach(createField())
watch(
() => props,
() => (fieldRef.value = checker(createField())),
{ deep: true }
)
watch([formRef, parentRef], () => (fieldRef.value = checker(createField())))

provide(FieldSymbol, fieldRef)

Expand Down
11 changes: 7 additions & 4 deletions packages/vue/src/components/FormProvider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { provide, defineComponent, toRaw } from 'vue-demi'
import { provide, defineComponent, watch } from 'vue-demi'
import { FormSymbol } from '../shared/context'
import { IProviderProps } from '../types'
import { useAttach } from '../hooks/useAttach'
Expand All @@ -17,10 +17,13 @@ export default defineComponent<IProviderProps>({
},
},
setup(props: IProviderProps, { attrs, slots }) {
const formRef = useAttach(
() => toRaw(props.form),
() => props.form
const getForm = () => props.form
const [formRef, checker] = useAttach(getForm())
watch(
() => props.form,
() => (formRef.value = checker(getForm()))
)

provide(FormSymbol, formRef)

return () => h(Fragment, { attrs }, slots)
Expand Down
Loading

0 comments on commit 837cfc0

Please sign in to comment.