diff --git a/src/components/feature/FeatureAttachmentForm.vue b/src/components/feature/FeatureAttachmentForm.vue
index eb9d0ef402eab0ff57f5623e7088c0c10637ee4b..c75905f2db595f7cee272a5d245ede78a522024f 100644
--- a/src/components/feature/FeatureAttachmentForm.vue
+++ b/src/components/feature/FeatureAttachmentForm.vue
@@ -11,7 +11,7 @@
           <i class="ui times icon"></i>
         </button>
       </h4>
-      {{ form.errors }}
+      <!-- {{ form.errors }} -->
       <div class="visible-fields">
         <div class="two fields">
           <div class="required field">
@@ -25,7 +25,11 @@
               v-model="form.title.value"
               @change="updateStore"
             />
-            {{ form.title.errors }}
+            <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>
@@ -46,7 +50,11 @@
               :name="form.attachment_file.html_name"
               :id="'attachment_file' + attachmentForm.dataKey"
             />
-            {{ form.attachment_file.errors }}
+            <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">
@@ -57,7 +65,7 @@
             v-model="form.info.value"
             @change="updateStore"
           ></textarea>
-          {{ form.info.errors }}
+          <!-- {{ form.info.errors }} -->
         </div>
       </div>
     </div>
@@ -75,7 +83,8 @@ export default {
       fileToImport: null,
       form: {
         title: {
-          errors: null,
+          errors: [],
+          id_for_error: `errorlist-title-${this.attachmentForm.dataKey}`,
           id_for_label: "titre",
           field: {
             max_length: 30, // todo : vérifier dans django
@@ -85,10 +94,11 @@ export default {
           value: "",
         },
         attachment_file: {
-          errors: null,
+          errors: [],
+          id_for_error: `errorlist-file-${this.attachmentForm.dataKey}`,
           html_name: "titre",
           label: "Titre",
-          value: "",
+          value: null,
         },
         info: {
           value: "",
@@ -109,19 +119,22 @@ export default {
     initForm(attachmentForm) {
       for (let el in attachmentForm) {
         if (el && this.form[el]) {
-          this.form[el].value =
-            el === "attachment_file"
-              ? attachmentForm[el].split("/").pop() //* keep only the file name, not the path
-              : attachmentForm[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
       );
     },
+
     updateStore() {
       this.$store.commit("feature/UPDATE_ATTACHMENT_FORM", {
         dataKey: this.attachmentForm.dataKey,
@@ -131,6 +144,7 @@ export default {
         fileToImport: this.fileToImport,
       });
     },
+
     onFileChange(e) {
       const files = e.target.files || e.dataTransfer.files;
       if (!files.length) return;
@@ -138,6 +152,28 @@ export default {
       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();
     },
+
+    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() {
diff --git a/src/components/feature/FeatureLinkedForm.vue b/src/components/feature/FeatureLinkedForm.vue
index 960f63371b388c965bfe623add3ba30b190030e4..80f10d776a4754d01cdcfb0d1568a566964d5e8b 100644
--- a/src/components/feature/FeatureLinkedForm.vue
+++ b/src/components/feature/FeatureLinkedForm.vue
@@ -10,7 +10,9 @@
         <i class="ui times icon"></i>
       </button>
     </h4>
-    {{ form.errors }}
+    <ul id="errorlist-links" class="errorlist">
+      <li v-for="error in form.errors" :key="error" v-html="error"></li>
+    </ul>
     <div class="visible-fields">
       <div class="two fields">
         <div class="required field">
@@ -53,8 +55,10 @@ export default {
   },
 
   computed: {
-    featureOptions: function() {
-      return this.features.map(el=> `${el.title} (${el.display_creator} - ${el.created_on})`) 
+    featureOptions: function () {
+      return this.features.map(
+        (el) => `${el.title} (${el.display_creator} - ${el.created_on})`
+      );
     },
     selected_relation_type: {
       // getter
@@ -92,7 +96,7 @@ export default {
           },
           html_name: "relation_type",
           label: "Type de liaison",
-          value: "",
+          value: "Doublon",
         },
         feature_to: {
           errors: null,
@@ -118,6 +122,19 @@ export default {
         feature_to: this.form.feature_to.value,
       });
     },
+    checkForm() {
+      if (this.form.feature_to.value === "") {
+        this.form.errors = [
+          "<strong>Choisir un signalement lié</strong><br/> Pourriez-vous choisir un signalement pour la nouvelle liaison ?",
+        ];
+        document
+          .getElementById("errorlist-links")
+          .scrollIntoView({ block: "start", inline: "nearest" });
+        return false;
+      }
+      this.form.errors = [];
+      return true;
+    },
   },
 };
 </script>
\ No newline at end of file
diff --git a/src/components/feature_type/FeatureTypeCustomForm.vue b/src/components/feature_type/FeatureTypeCustomForm.vue
index fcdf282ddc87b864f5ade32573d867e6c2cf2455..140a62b0765e06417bb45fb7e03a1283aebac863 100644
--- a/src/components/feature_type/FeatureTypeCustomForm.vue
+++ b/src/components/feature_type/FeatureTypeCustomForm.vue
@@ -271,8 +271,6 @@ export default {
       return string.replace(/\s*,\s*/gi, ",");
     },
     checkCustomForm() {
-      console.log("checkCustomForm");
-      console.log(this.form);
       if (this.form.label.value === null) {
         this.form.label.errors = ["Veuillez compléter ce champ."];
         return false;
diff --git a/src/views/feature/Feature_edit.vue b/src/views/feature/Feature_edit.vue
index f3eeb428dbbc3537d32acf7984cc1052a7c06d3a..e4d5c62ce0ec448bf8c2fcc677b446e5056a636d 100644
--- a/src/views/feature/Feature_edit.vue
+++ b/src/views/feature/Feature_edit.vue
@@ -30,7 +30,7 @@
               v-model="form.title.value"
               @blur="updateStore"
             />
-            <ul id="errorlist" class="errorlist">
+            <ul id="errorlist-title" class="errorlist">
               <li v-for="error in form.title.errors" :key="error">
                 {{ error }}
               </li>
@@ -45,11 +45,6 @@
               :selected="selected_status.name"
               :selection.sync="selected_status"
             />
-            <ul id="errorlist" class="errorlist">
-              <li v-for="error in form.status.errors" :key="error">
-                {{ error }}
-              </li>
-            </ul>
           </div>
         </div>
         <div class="field">
@@ -62,7 +57,6 @@
             v-model="form.description.value"
             @blur="updateStore"
           ></textarea>
-          {{ form.description.errors }}
         </div>
 
         <!-- Geom Field -->
@@ -145,8 +139,11 @@
               <br />
             </span>
           </div>
-
-          {{ form.geom.errors }}
+          <ul id="errorlist-geom" class="errorlist">
+            <li v-for="error in form.geom.errors" :key="error">
+              {{ error }}
+            </li>
+          </ul>
           <!-- Map -->
           <input
             type="hidden"
@@ -179,14 +176,12 @@
 
         <!-- Pièces jointes -->
         <div class="ui horizontal divider">PIÈCES JOINTES</div>
-        <!-- {{ attachment_formset.non_form_errors }} -->
-
         <div id="formsets-attachment">
-          <!-- {{ attachment_formset.management_form }} -->
           <FeatureAttachmentForm
             v-for="form in attachmentFormset"
             :key="form.dataKey"
             :attachmentForm="form"
+            ref="attachementForm"
           />
         </div>
 
@@ -201,15 +196,13 @@
 
         <!-- Signalements liés -->
         <div class="ui horizontal divider">SIGNALEMENTS LIÉS</div>
-        <!-- {{ linked_formset.non_form_errors }} -->
         <div id="formsets-link">
-          <!-- {{ linked_formset.management_form }} -->
-
           <FeatureLinkedForm
             v-for="form in linkedFormset"
             :key="form.dataKey"
             :linkedForm="form"
             :features="features"
+            ref="linkedForm"
           />
         </div>
         <button
@@ -282,7 +275,7 @@ export default {
       ],
       form: {
         title: {
-          errors: null,
+          errors: [],
           id_for_label: "name",
           field: {
             max_length: 30,
@@ -292,7 +285,6 @@ export default {
           value: "",
         },
         status: {
-          errors: null,
           id_for_label: "status",
           html_name: "status",
           label: "Statut",
@@ -302,13 +294,14 @@ export default {
           },
         },
         description: {
-          errors: null,
+          errors: [],
           id_for_label: "description",
           html_name: "description",
           label: "Description",
           value: "",
         },
         geom: {
+          errors: [],
           label: "Localisation",
           value: null,
         },
@@ -339,12 +332,10 @@ export default {
 
     selected_status: {
       get() {
-        console.log(this.form.status.value);
         return this.form.status.value;
       },
       set(newValue) {
         this.form.status.value = newValue;
-        console.log(this.form.status.value);
         this.updateStore();
       },
     },
@@ -484,29 +475,63 @@ export default {
       });
     },
 
-    checkForms() {
+    checkFormTitle() {
       if (this.form.title.value) {
         this.form.title.errors = [];
-        return this.checkCustomForms(); //* if customForms are ok, validate, if get out function
+        return true;
       } else if (
-        !this.form.title.errors.includes("Veuillez compléter ce champ.") // TODO : Gérer les autres champs
+        !this.form.title.errors.includes("Veuillez compléter ce champ.")
       ) {
         this.form.title.errors.push("Veuillez compléter ce champ.");
         document
-          .getElementById("errorlist")
+          .getElementById("errorlist-title")
+          .scrollIntoView({ block: "end", inline: "nearest" });
+      }
+      return false;
+    },
+
+    checkFormGeom() {
+      if (this.form.geom.value) {
+        this.form.geom.errors = [];
+        return true;
+      } else if (
+        !this.form.geom.errors.includes("Valeur géométrique non valide.")
+      ) {
+        this.form.geom.errors.push("Valeur géométrique non valide.");
+        document
+          .getElementById("errorlist-geom")
           .scrollIntoView({ block: "end", inline: "nearest" });
       }
       return false;
     },
 
+    checkAddedForm() {
+      let isValid = true; //* fallback if all customForms returned true
+      if (this.$refs.attachementForm) {
+        for (const attachementForm of this.$refs.attachementForm) {
+          if (attachementForm.checkForm() === false) {
+            isValid = false;
+          }
+        }
+      }
+      if (this.$refs.linkedForm) {
+        for (const linkedForm of this.$refs.linkedForm) {
+          if (linkedForm.checkForm() === false) {
+            isValid = false;
+          }
+        }
+      }
+      return isValid;
+    },
+
     postForm() {
-      if (!this.checkForms()) return;
-      this.$store.dispatch("feature/SEND_FEATURE", this.currentRouteName);
-      // if (this.form.title.value) {
-      //   this.form.title.errors = null;
-      // } else {
-      //   this.form.title.errors = "Veuillez compléter ce champ.";
-      // }
+      if (
+        this.checkFormTitle() &&
+        this.checkFormGeom() &&
+        this.checkAddedForm()
+      ) {
+        this.$store.dispatch("feature/SEND_FEATURE", this.currentRouteName);
+      }
     },
 
     onFeatureTypeLoaded() {
@@ -788,8 +813,8 @@ export default {
       "feature_type/SET_CURRENT_FEATURE_TYPE_SLUG",
       this.$route.params.slug_type_signal
     );
-    // todo : mutualize in store with feature_detail.vue
 
+    // todo : mutualize in store with feature_detail.vue
     if (this.$route.params.slug_signal) {
       featureAPI
         .getFeatureAttachments(this.$route.params.slug_signal)
@@ -805,8 +830,6 @@ export default {
     this.initMap();
   },
 };
-
-// TODO : add script from django and convert:
 </script>
 
 <style>
diff --git a/src/views/feature_type/Feature_type_edit.vue b/src/views/feature_type/Feature_type_edit.vue
index 9ee84d79746003c495b5e777909ccca178b2af23..50aa59cad812c431491a02fda2f8e651b62f5a36 100644
--- a/src/views/feature_type/Feature_type_edit.vue
+++ b/src/views/feature_type/Feature_type_edit.vue
@@ -308,7 +308,7 @@ export default {
         // * find feature_type and fill form values
         if (this.form[el]) this.form[el].value = formData[el];
       }
-      //! add custom fields using ONLY this function, incrementing dataKey for Vue updating correctly components
+      //! add custom fields using ONLY this function, incrementing dataKey for Vue to correctly update components
       formData.customfield_set.forEach((el) => this.addCustomForm(el));
       this.updateStore();
     },
@@ -341,7 +341,7 @@ export default {
         this.form.title.errors = [];
         return this.checkCustomForms(); //* if customForms are ok, validate, if get out function
       } else if (
-        !this.form.title.errors.includes("Veuillez compléter ce champ.") // TODO : Gérer les autres champs
+        !this.form.title.errors.includes("Veuillez compléter ce champ.")
       ) {
         this.form.title.errors.push("Veuillez compléter ce champ.");
         document
diff --git a/src/views/project/Project_edit.vue b/src/views/project/Project_edit.vue
index b20ef2476d7aeb564142ff6cfd06eaf392444f29..8d5830d0b111376a8d314173aaa6e35755b1f663 100644
--- a/src/views/project/Project_edit.vue
+++ b/src/views/project/Project_edit.vue
@@ -303,9 +303,6 @@ export default {
 
     checkForm() {
       for (const key in this.errors) {
-        console.log(key);
-        console.log(this.form[key]);
-        console.log(this.form[key].value);
         if ((key === "title" && this.form[key]) || this.form[key].value) {
           this.errors[key] = [];
         } else if (!this.errors[key].length) {
@@ -314,7 +311,6 @@ export default {
               ? "Veuillez compléter ce champ."
               : "Sélectionnez un choix valide. Ce choix ne fait pas partie de ceux disponibles."
           );
-          console.log(`errorlist-${key}`);
           document
             .getElementById(`errorlist-${key}`)
             .scrollIntoView({ block: "end", inline: "nearest" });