Finalisation de la fogique du composant MovieCommentForm avec la gestion de la v…
…alidation au submit + la création d'un event pour remonter les data au parent pour gestion.
Showing
2 changed files
with
48 additions
and
21 deletions
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | +//#region --Import--. | ||
| 2 | import { useVuelidate } from "@vuelidate/core"; | 3 | import { useVuelidate } from "@vuelidate/core"; |
| 3 | -import { helpers, maxLength, minLength, required, minValue, maxValue } from "@vuelidate/validators"; | 4 | +import { helpers, maxLength, maxValue, minLength, minValue, required } from "@vuelidate/validators"; |
| 5 | +//#endregion | ||
| 4 | 6 | ||
| 5 | -// type FormData = { | 7 | +//#region --Emit--. |
| 6 | -// username: string | 8 | +const emit = defineEmits(['event:submit']); |
| 7 | -// message: string | 9 | +//#endregion |
| 8 | -// rating: number | ||
| 9 | -// }; | ||
| 10 | 10 | ||
| 11 | -type FormData = { [key: string]: string|number }; | 11 | +//#region --Props--. |
| 12 | +defineProps({ | ||
| 13 | + isSubmitting: { | ||
| 14 | + type: Boolean, | ||
| 15 | + required: false, | ||
| 16 | + nullable: false, | ||
| 17 | + default: false, | ||
| 18 | + }, | ||
| 19 | +}); | ||
| 20 | +//#endregion | ||
| 12 | 21 | ||
| 13 | //#region --Data/ref--. | 22 | //#region --Data/ref--. |
| 14 | const initialState = { | 23 | const initialState = { |
| @@ -33,11 +42,11 @@ const rules = { | @@ -33,11 +42,11 @@ const rules = { | ||
| 33 | minLength: helpers.withMessage("Le message doit contenir au moins 3 caractères", minLength(3)), | 42 | minLength: helpers.withMessage("Le message doit contenir au moins 3 caractères", minLength(3)), |
| 34 | maxLength: helpers.withMessage("Le message ne peut pas dépasser 500 caractères", maxLength(500)), | 43 | maxLength: helpers.withMessage("Le message ne peut pas dépasser 500 caractères", maxLength(500)), |
| 35 | }, | 44 | }, |
| 36 | - rating:{ | 45 | + rating: { |
| 37 | required: helpers.withMessage("La notation est requise", required), | 46 | required: helpers.withMessage("La notation est requise", required), |
| 38 | minValue: helpers.withMessage("Le message ne être inférieure à 0", minValue(0)), | 47 | minValue: helpers.withMessage("Le message ne être inférieure à 0", minValue(0)), |
| 39 | maxValue: helpers.withMessage("Le message ne être suppérieur à 10", maxValue(10)), | 48 | maxValue: helpers.withMessage("Le message ne être suppérieur à 10", maxValue(10)), |
| 40 | - } | 49 | + }, |
| 41 | }; | 50 | }; |
| 42 | 51 | ||
| 43 | const formData = reactive({ | 52 | const formData = reactive({ |
| @@ -46,28 +55,27 @@ const formData = reactive({ | @@ -46,28 +55,27 @@ const formData = reactive({ | ||
| 46 | const v$ = useVuelidate(rules, formData); | 55 | const v$ = useVuelidate(rules, formData); |
| 47 | //#endregion | 56 | //#endregion |
| 48 | 57 | ||
| 49 | -function submitComment() { | 58 | +//#region --Function--. |
| 50 | - console.log("Submit !") | 59 | +async function submitComment() { |
| 60 | + emit('event:submit', formData); | ||
| 51 | } | 61 | } |
| 52 | 62 | ||
| 53 | -function clear () { | 63 | +function clear() { |
| 54 | v$.value.$reset(); | 64 | v$.value.$reset(); |
| 55 | formData.username = initialState.username; | 65 | formData.username = initialState.username; |
| 56 | formData.message = initialState.message; | 66 | formData.message = initialState.message; |
| 57 | formData.rating = initialState.rating; | 67 | formData.rating = initialState.rating; |
| 58 | } | 68 | } |
| 59 | 69 | ||
| 60 | -// :error-messages="getErrors('username', $v.username)" :counter="10" label="username" | 70 | +//#endregion |
| 61 | -// :error-messages="getErrors('message', $v.message)" | ||
| 62 | </script> | 71 | </script> |
| 63 | 72 | ||
| 64 | <template> | 73 | <template> |
| 65 | <section> | 74 | <section> |
| 66 | - movie comment form | 75 | + <VForm> |
| 67 | - <VForm @submit.prevent="submitComment"> | ||
| 68 | <v-text-field | 76 | <v-text-field |
| 69 | v-model="formData.username" | 77 | v-model="formData.username" |
| 70 | - :error-messages="v$.username.$errors.map(e => e.$message)" | 78 | + :error-messages="v$.username.$errors.map((e) => e.$message)" |
| 71 | label="nom d'utilisateur" | 79 | label="nom d'utilisateur" |
| 72 | placeholder="nom d'utilisateur" | 80 | placeholder="nom d'utilisateur" |
| 73 | required | 81 | required |
| @@ -76,7 +84,7 @@ function clear () { | @@ -76,7 +84,7 @@ function clear () { | ||
| 76 | /> | 84 | /> |
| 77 | <v-textarea | 85 | <v-textarea |
| 78 | v-model="formData.message" | 86 | v-model="formData.message" |
| 79 | - :error-messages="v$.message.$errors.map(e => e.$message)" | 87 | + :error-messages="v$.message.$errors.map((e) => e.$message)" |
| 80 | label="message" | 88 | label="message" |
| 81 | placeholder="Saisissez votre commentaire" | 89 | placeholder="Saisissez votre commentaire" |
| 82 | required | 90 | required |
| @@ -85,7 +93,7 @@ function clear () { | @@ -85,7 +93,7 @@ function clear () { | ||
| 85 | /> | 93 | /> |
| 86 | <v-text-field | 94 | <v-text-field |
| 87 | v-model="formData.rating" | 95 | v-model="formData.rating" |
| 88 | - :error-messages="v$.rating.$errors.map(e => e.$message)" | 96 | + :error-messages="v$.rating.$errors.map((e) => e.$message)" |
| 89 | label="Note (1-10)" | 97 | label="Note (1-10)" |
| 90 | placeholder="" | 98 | placeholder="" |
| 91 | required | 99 | required |
| @@ -93,7 +101,25 @@ function clear () { | @@ -93,7 +101,25 @@ function clear () { | ||
| 93 | @blur="v$.rating.$touch" | 101 | @blur="v$.rating.$touch" |
| 94 | @input="v$.rating.$touch" | 102 | @input="v$.rating.$touch" |
| 95 | /> | 103 | /> |
| 96 | - <v-btn class="mr-4">submit</v-btn> | 104 | + <v-btn |
| 105 | + class="mt-6 mr-4" | ||
| 106 | + color="primary" | ||
| 107 | + @click=" | ||
| 108 | + async () => { | ||
| 109 | + const validForm = await v$.$validate(); | ||
| 110 | + if (validForm) { | ||
| 111 | + submitComment(); | ||
| 112 | + } | ||
| 113 | + } | ||
| 114 | + " | ||
| 115 | + > | ||
| 116 | + <span v-if="isSubmitting" class="flex items-center justify-center"> | ||
| 117 | + <span class="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin mr-2" /> | ||
| 118 | + Envoi en cours... | ||
| 119 | + </span> | ||
| 120 | + <span v-else>Publier le commentaire</span> | ||
| 121 | + </v-btn> | ||
| 122 | + <v-btn class="mt-6 mr-4" color="primary" @click="clear"> effacer </v-btn> | ||
| 97 | </VForm> | 123 | </VForm> |
| 98 | </section> | 124 | </section> |
| 99 | </template> | 125 | </template> |
| @@ -19,6 +19,7 @@ const { currentRoute } = useRouter(); | @@ -19,6 +19,7 @@ const { currentRoute } = useRouter(); | ||
| 19 | 19 | ||
| 20 | //#region --Data/ref--. | 20 | //#region --Data/ref--. |
| 21 | const isLoading = ref(true); | 21 | const isLoading = ref(true); |
| 22 | +const isSubmitting = ref(false); | ||
| 22 | //#endregion | 23 | //#endregion |
| 23 | 24 | ||
| 24 | //#region --Computed--. | 25 | //#region --Computed--. |
| @@ -177,7 +178,7 @@ onMounted(() => { | @@ -177,7 +178,7 @@ onMounted(() => { | ||
| 177 | </div> | 178 | </div> |
| 178 | </div> | 179 | </div> |
| 179 | <!-- Comments form. --> | 180 | <!-- Comments form. --> |
| 180 | - <form-movie-comment-form /> | 181 | + <form-movie-comment-form @event:submit="console.log('submitted !', $event)" /> |
| 181 | </section> | 182 | </section> |
| 182 | </div> | 183 | </div> |
| 183 | </div> | 184 | </div> |
-
Please register or login to post a comment