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