<template> <div> <div class="ui teal segment"> <h4> Pièce jointe <button @click="removeAttachmentFormset(form.dataKey)" class="ui small compact right floated icon button remove-formset" type="button" > <i class="ui times icon"></i> </button> </h4> <!-- {{ form.errors }} --> <div class="visible-fields"> <div class="two fields"> <div class="required field"> <label :for="form.title.id_for_label">{{ form.title.label }}</label> <input type="text" required :maxlength="form.title.field.max_length" :name="form.title.html_name" :id="form.title.id_for_label" v-model="form.title.value" /> <ul :id="form.title.id_for_error" class="errorlist"> <li v-for="error in form.title.errors" :key="error"> {{ error }} </li> </ul> </div> <div class="required field"> <label>Fichier (PDF, PNG, JPEG)</label> <label class="ui icon button" :for="'attachment_file' + attachmentForm.dataKey" > <i class="file icon"></i> <span v-if="form.attachment_file.value" class="label">{{ form.attachment_file.value }}</span> <span v-else class="label">Sélectionner un fichier ... </span> </label> <input @change="onFileChange" type="file" accept="application/pdf, image/jpeg, image/png" style="display: none" :name="form.attachment_file.html_name" :id="'attachment_file' + attachmentForm.dataKey" /> <ul :id="form.attachment_file.id_for_error" class="errorlist"> <li v-for="error in form.attachment_file.errors" :key="error"> {{ error }} </li> </ul> </div> </div> <div class="field"> <label for="form.info.id_for_label">{{ form.info.label }}</label> <textarea name="form.info.html_name" rows="5" v-model="form.info.value" ></textarea> <!-- {{ form.info.errors }} --> </div> </div> </div> </div> </template> <script> export default { name: "FeatureAttachmentFormset", props: ["attachmentForm"], data() { return { fileToImport: null, form: { id: { value: "", errors: null, label: "ID", }, title: { errors: [], id_for_error: `errorlist-title-${this.attachmentForm.dataKey}`, id_for_label: "titre", field: { max_length: 30, // todo : vérifier dans django }, html_name: "titre", label: "Titre", value: "", }, attachment_file: { errors: [], id_for_error: `errorlist-file-${this.attachmentForm.dataKey}`, html_name: "titre", label: "Titre", value: null, }, info: { value: "", errors: null, label: "Info", }, }, }; }, watch: { attachmentForm(newValue) { this.initForm(newValue); }, //* utilisation de watcher, car @change aurait un délai "form.title.value": function (newValue, oldValue) { if (oldValue !== "") { if (newValue !== oldValue) { this.updateStore(); } } }, "form.info.value": function (newValue, oldValue) { if (oldValue !== "") { if (newValue !== oldValue) { this.updateStore(); } } }, }, methods: { initForm(attachmentForm) { for (let el in attachmentForm) { if (el && this.form[el]) { if (el === "attachment_file" && attachmentForm[el]) { this.form[el].value = attachmentForm[el].split("/").pop(); //* keep only the file name, not the path } else { this.form[el].value = attachmentForm[el]; } } } }, removeAttachmentFormset() { this.$store.commit( "feature/REMOVE_ATTACHMENT_FORM", this.attachmentForm.dataKey ); if (this.form.id.value) this.$store.commit("feature/ADD_ATTACHMENT_TO_DELETE", this.form.id.value); }, updateStore() { const data = { id: this.form.id.value, dataKey: this.attachmentForm.dataKey, title: this.form.title.value, attachment_file: this.form.attachment_file.value, info: this.form.info.value, fileToImport: this.fileToImport, }; this.$store.commit("feature/UPDATE_ATTACHMENT_FORM", data); }, validateImgFile(files, handleFile) { let url = window.URL || window.webkitURL; let image = new Image(); image.onload = function () { handleFile(true); }; image.onerror = function () { handleFile(false); }; image.src = url.createObjectURL(files); URL.revokeObjectURL(image.src); }, onFileChange(e) { // * read image file const files = e.target.files || e.dataTransfer.files; const _this = this; //* 'this' is different in onload function function handleFile(isValid) { if (isValid) { _this.fileToImport = files[0]; //* store the file to post later _this.form.attachment_file.value = files[0].name; //* add name to the form for display, in order to match format return from API _this.updateStore(); _this.form.attachment_file.errors = []; } else { _this.form.attachment_file.errors.push( "Transférez une image valide. Le fichier que vous avez transféré n'est pas une image, ou il est corrompu." ); } } if (files.length) { //* exception for pdf if (files[0].type === "application/pdf") { handleFile(true); } else { this.form.attachment_file.errors = []; //* check if file is an image and pass callback to handle file this.validateImgFile(files[0], handleFile); } } }, checkForm() { let isValid = true; if (this.form.title.value === "") { this.form.title.errors = ["Veuillez compléter ce champ."]; document .getElementById(this.form.title.id_for_error) .scrollIntoView({ block: "start", inline: "nearest" }); isValid = false; } else if (this.form.attachment_file.value === null) { this.form.attachment_file.errors = ["Veuillez compléter ce champ."]; this.form.title.errors = []; document .getElementById(this.form.attachment_file.id_for_error) .scrollIntoView({ block: "start", inline: "nearest" }); isValid = false; } else { this.form.title.errors = []; this.form.attachment_file.errors = []; } return isValid; }, }, mounted() { this.initForm(this.attachmentForm); }, }; </script>