首页 > 解决方案 > (Vue) 我无法让现有数据显示在编辑表单中

问题描述

我有一个允许 CRUD 操作的站点,现在我有一个页面显示一个文档和我放入其中的数据,然后将文档吹到有一个表单,我可以在其中输入新数据并更新文档。但从 UI 的角度来看,这不是很实用。如果我可以在我用来更新的表单内显示现有数据,我会更喜欢。

我希望我说清楚?我希望在表单中显示现有数据,而不是只输入一些新数据的空白表单,以防我只想编辑单行文本或类似内容。

下面我将向您展示代码,然后我将向您展示我为解决此问题所做的尝试。

可组合处理更新函数本身:

const useDocument = (collection, id) => {
const error = ref(null)
const isPending = ref(false)

let docRef = projectFirestore.collection(collection).doc(id)

const updateDoc = async (updates) => {
    isPending.value = true
    error.value = null
    try {
        const res = await docRef.update(updates) 
        isPending.value = false
        return res
    }catch(err) {
        console.log(err.message)
        isPending.value = false
        error.value = 'Could not update document'
    }
}

然后我有一个组件,我在其中使用表单更新现有文档

template>
    <div class="Hero-Section-Edit">
      <form @submit.prevent="handleSubmit">
      <input type="text" required placeholder="Change title" v-model="title">
            <label>Change image</label>
      <input type="file" @change="handleChange">
      <div class="error">{{ fileError }}</div>
      <button v-if="!isPending">Update</button>
      <button v-else disabled>Updating...</button>
   </form>
    </div>
</template>

<script>
import { ref } from 'vue'
import { useRouter } from 'vue-router' 
import useDocument from '@/composables/useDocument'
import useStorage from '@/composables/useStorage'
import useCollection from '@/composables/useCollection'
export default {
    props: ['content'],
    setup(props) {
        const title = ref('')
        const { filePath, url, uploadImage } = useStorage()
        const file = ref(null)
        const fileError = ref(null)
        const { error } = useCollection()
        const isPending = ref(false)
        const router = useRouter();

        const handleSubmit = async () => {
    if (!props.content) return
    const { updateDoc } = useDocument('gershoej', props.content.id)
            await uploadImage(file.value)
            await updateDoc({
                title: title.value,
                imageUrl: url.value,
                filePath: filePath.value,
            })
                isPending.value = false
                if(!error.value) {
                router.push({ name: "Home" })
             }
        }

        // allowed file types

       const types = ['image/png', 'image/jpeg']

       const handleChange = (e) => {
          const selected = e.target.files[0]
          console.log(selected)

          if (selected && types.includes(selected.type)) {
             file.value = selected
             fileError.value = null 
          } else {
             file.value = null
             fileError.value = 'Please select an image of the type JPG or PNG'
          }
       }

        return {
            title,
            url,
            handleSubmit,
            handleChange,
            fileError,
            isPending,
            error
        }
    }
}
</script>

最后,我有一个组件,可以在其中查看文档并导入更新表单。

<template>
        <div v-if="content" class="Hero-Section-Details">
                    <img :src="content.imageUrl">
                    <h2> {{ content.title }}</h2>
                </div>
            </div>
        </div>
        <button @click="handleDelete">Delete</button>
        <HeroSectionEdit :content="content" />
</template>

<script>
import HeroSectionEdit from './HeroSectionEdit'
import useDocument from '@/composables/useDocument'
import getDocument from '@/composables/getDocument'
import useStorage from '@/composables/useStorage'
import { useRouter } from "vue-router";
export default {
    props: ['id'],
    components: { HeroSectionEdit },
    setup(props) {
        const { document: content } = getDocument('gershoej', props.id)
        const { deleteDoc } = useDocument('gershoej', props.id)
        const router = useRouter();
        const { deleteImage } = useStorage()

      const handleDelete = async () => {
          await deleteImage(content.value.filePath)
          await deleteDoc()
          confirm('Do you wish to delete this content?')
          router.push({ name: "Home" });
      }

        return {
            content,
            handleDelete
        }
    }
}
</script>

我试图做的是将 content.title 添加到表单中,而不仅仅是标题。

v-model="content.title"

这确实使现有数据出现在表单中,但是我收到一个错误: 无法读取 null 的属性“标题” 并且我无法更新文件。

有谁知道解决方案?

标签: vue.js

解决方案


看起来您在content从 getDocument 获取之前渲染组件(我猜它正在返回一个承诺)。

在访问其属性之前,您需要确保内容中有一个实际对象。


推荐阅读