Reputation: 67
This is the first time I try to upload a file from a client (Vue.js), through a server (Node.js, Express.js) to a database (MongoDB).
I would like to do it without any library.
The logic I'm trying to implement is the following: user can upload a file from an input. This file (can only be an image) is encoded to base64. Then it is sent to the server and recorded in the database as a string. It actually works. Data provided are well recorded in the database. But it also generates these errors:
This error appears just after loading the image in the input.
Theses errors appear just after submitting the form.
<script setup>
import FormInputMolecule from "#/molecules/FormInput.vue";
import ButtonAtom from "#/atoms/Button.vue";
import { computed, ref } from "vue";
import { useRouter } from "vue-router";
import { useSkillStore } from "@/store/skillStore";
import { skillSchema } from "@/validations/skillSchema";
import { validationErrors, validateData } from "@/services/yup";
const router = useRouter();
const skillStore = useSkillStore();
const loading = computed(() => skillStore.loaders.createSkill);
const skillData = ref({
name: null,
image: null,
progress: null,
});
const previewImage = async (event) => {
const preview = document.getElementById("preview-image");
skillData.value.image = event.target.files[0];
if (skillData.value.image) {
const imageUrl = URL.createObjectURL(skillData.value.image);
preview.src = imageUrl;
} else {
preview.src = "";
}
};
const toBase64 = (file) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
const resetError = (field) => {
if (validationErrors.value.skillCreationForm?.[field]) {
validationErrors.value.skillCreationForm[field] = null;
}
};
const createSkill = async () => {
try {
validationErrors.value["skillCreationForm"] = {};
const isValid = await validateData(
["skillCreationForm"],
skillSchema,
skillData.value
);
if (!isValid) return;
skillData.value.image = await toBase64(skillData.value.image);
skillData.value.progress = parseInt(skillData.value.progress);
await skillStore.createSkill(skillData.value);
console.log(skillData.value);
router.push({ name: "skills" });
} catch (error) {
console.error(error);
}
};
</script>
<template>
<form @submit.prevent="createSkill">
<form-input-molecule
label="Compétence"
id="name"
name="name"
v-model="skillData.name"
placeholder="Exemple: JavaScript"
:error-message="validationErrors.skillCreationForm?.name"
@input="resetError('name')"
></form-input-molecule>
<form-input-molecule
label="Image"
id="image"
name="image"
type="file"
v-model="skillData.image"
:error-message="validationErrors.skillCreationForm?.image"
@change="previewImage"
@input="resetError('image')"
></form-input-molecule>
<img id="preview-image" width="100" />
<form-input-molecule
label="Progression"
id="progress"
name="progress"
type="number"
v-model="skillData.progress"
placeholder="Exemple: 60"
:min="0"
:max="100"
:error-message="validationErrors.skillCreationForm?.progress"
@input="resetError('progress')"
></form-input-molecule>
<div class="button-wrapper">
<button-atom type="submit" :loading="loading">Créer</button-atom>
</div>
</form>
</template>
I really do not know where these errors are coming from. If you guys could please help me.
Upvotes: 0
Views: 101
Reputation: 359
If you can put up this code in stackblitz etc with all your dependencies it might be easier for people to help you.
Nevertheless, based on the error messages you have received..regarding the first error...
You have used a v-model for input element which is skillData.image
and in the createSkill
function you are assigning it a base64 value
skillData.value.image = await toBase64(skillData.value.image);
I think the error is saying that this input field can only have the file name. So maybe you want to look at why you are doing this update. You can just store it in a const.
Regarding the second error, it seems that the Skills route is loading before the values required for that page are received. So maybe you can try to do a v-if in on the skills page to only load on data received. Unable to dig more as you have not shared that page.
Upvotes: 1