TL;DR
Есть ли способ загрузить асинхронные данные в <FormKitSchema>
?
Я пытаюсь получить асинхронные данные и загрузить их в форму FormKit, сгенерированную из схемы JSON (<FormKitSchema>
). Кажется, я не могу найти пример, и я пробовал несколько способов сделать это, но мне не повезло.
Я понимаю, что свойство value
элемента input
будет использоваться только при первоначальном рендеринге, что круто. Однако я не могу сначала получить данные, а затем условно загрузить <FormKitSchema>
(использование v-if
ничем не помогло). Похоже, рендеринг должен выполняться с начальной загрузкой компонента, иначе ничего не появится.
Пример: formComponent.vue
(<FormComponent>
)
<template>
<FormKitSchema :schema = "schema" :data = "asyncData"/>
</template>
<script setup>
import {reactive, ref} from 'vue';
const getData = async () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({name: "How do I get this into the form???"})
}, 1500)
})
};
const asyncData = reactive({
userData: await getData(), // Using 'await' here seems to prevent the form from ever loading
submit: async (formData, node) => {
console.info("submit: ", {formData, node});
}
})
const schema = [
{
$cmp: 'FormKit',
props: {
type: 'form',
id: 'form',
onSubmit: '$submit',
plugins: '$plugins',
actions: false,
},
children: [
{
$formkit: 'text',
name: 'fullname',
label: '*Full Name',
placeholder: 'Full Name',
value: "$userData.name",
validation: 'required'
},
{
$formkit: 'submit',
label: 'Save',
disabled: '$get(form).state.valid !== true'
}
]
}
]
</script>
Оказывается, это не проблема или проблема ни с FormKit
, ни с FormKitSchema
. Это проблема с использованием await
внутри функции reactive()
Vue.
Чтобы использовать значение разрешения промиса (т. е. userData: await getData()
) в начальном объекте аргумента reactive()
компонента (как в примере formComponent.vue
), вызывающий/родительский компонент должен поместить их в тег <Suspense>
. В противном случае Vue, по-видимому, просто не отображает компонент вообще, поэтому не было никаких ошибок и ничего не отображалось.
Из документации Vue.js на Suspense...
A component with async setup() must be nested in a <Suspense> in order to be rendered.
Поэтому с кодом formComponent.vue
в вопросе все в порядке. Просто нужно было добавить тег <Suspense>
в шаблон везде, где используется <FormComponent>
. Например...
Пример: parentView.vue
<Suspense>
<FormComponent/>
</Suspense>
ПРИМЕЧАНИЕ. На момент написания этой статьи элемент <Suspense>
является экспериментальным и может измениться.