我的日期選擇器欄位上的 v-model 綁定無法正常運作。
當您做出選擇時,它將在螢幕上即時更新,但它不會將值儲存在 formValues 反應物件中。
由於 vee-validate 不支援日期選擇器字段,我如何強制它更新到我的所有其他輸入字段都映射到的相同反應組件(formValues)。
<template> <img alt="Vue logo" src="./assets/logo.png"> <div v-if="showUnderAge.isVisible"> SORRY WE CANT HELP UNDER 18 </div> <div v-if="showOutOfCountry.isVisible"> SORRY WE CANT HELP OUT OF COUNTRY </div> <div v-if="showContainer.isVisible"> <h1>Create your Account</h1> Verify Entry values: <br /> {{ formValues }} <Form @submit="nextStep" :validation-schema="currentSchema" v-slot="{ handleSubmit }" > <template v-if="currentStep === 0"> <label for="name">Name</label> <Field name="name" id="name" v-model="formValues.name" /> <ErrorMessage name="name" /> <br /> <label for="email">Email</label> <Field name="email" id="email" type="email" v-model="formValues.email" /> <ErrorMessage name="email" /> <br /> <label for="country">Country</label> <Field as="select" name="country" v-model="formValues.country"> <option value="United States">United States</option> <option value="Canada">Canada</option> <option value="-" disabled>---------------</option> <option value="Afghanistan">Afghanistan</option> <option value="Åland Islands">Åland Islands</option> <option value="Albania">Albania</option> <option value="Algeria">Algeria</option> <option value="American Samoa">American Samoa</option> <option value="Andorra">Andorra</option> <option value="Angola">Angola</option> <option value="Anguilla">Anguilla</option> <option value="Antarctica">Antarctica</option> <option value="Antigua and Barbuda">Antigua and Barbuda</option> </Field> <br /> <label for="dob">Date of Birth</label> <Datepicker autoApply name="dob" v-model="formValues.date" :enableTimePicker="false" style="width: 20%"></Datepicker> <br /> </template> <template v-if="currentStep === 1"> <label for="password">Password</label> <Field name="password" type="password" id="password" v-model="formValues.password" /> <ErrorMessage name="password" /> <label for="confirmation">Confirm Password</label> <Field name="confirmPassword" type="password" id="confirmation" v-model="formValues.password" /> <ErrorMessage name="confirmPassword" /> </template> <template v-if="currentStep === 2"> <label for="address">Address</label> <Field as="textarea" name="address" id="address" v-model="formValues.address" /> <ErrorMessage name="address" /> <label for="postalCode">Postal Code</label> <Field name="postalCode" id="postalCode" v-model="formValues.postalCode" /> <ErrorMessage name="postalCode" /> </template> <template v-if="currentStep === 3"> <label for="terms">Agree to terms and conditions</label> <Field name="terms" type="checkbox" id="terms" :value="true" v-model="formValues.terms" /> <ErrorMessage name="terms" /> </template> <button v-if="currentStep !== 0" type="button" @click="prevStep"> Previous </button> <button v-if="currentStep !== 3" type="submit">Next</button> <button v-if="currentStep === 3" type="submit">Finish</button> </Form> </div> </template> <script> import { Form, Field, ErrorMessage } from "vee-validate"; import * as yup from "yup"; import { ref, reactive, computed } from "vue"; import Datepicker from 'vue3-date-time-picker'; import 'vue3-date-time-picker/dist/main.css'; import moment from 'moment'; export default { name: "App", components: { Form, Field, ErrorMessage, Datepicker }, setup: () => { const currentStep = ref(0); // since vee-validate removes values from the values object once the fields are unmounted // we would need to accumlate them manually const formValues = reactive({}); const showContainer = ref({isVisible: true}); const showOutOfCountry = ref({isVisible: false}); const showUnderAge = ref({isVisible: false}); const schemas = [ yup.object({ name: yup.string().required(), email: yup.string().required().email(), }), yup.object({ password: yup.string().required().min(6), confirmPassword: yup .string() .required() .min(6) .oneOf([yup.ref("password")], "Passwords must match"), }), yup.object({ address: yup.string().required(), postalCode: yup .string() .required() .matches(/^[0-9]+$/, "Must be numeric"), }), yup.object({ terms: yup.bool().required().equals([true]), }), ]; const currentSchema = computed(() => { return schemas[currentStep.value]; }); function getAge(dateString){ var today = new Date(); var birthDate = new Date(dateString); var age = today.getFullYear() - birthDate.getFullYear(); var m = today.getMonth() - birthDate.getMonth(); if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) { age--; } return age; } function nextStep(values) { console.log(currentStep.value) console.log(values) // Age kickout here for entire block let dobDt = moment(values.dob).format("YYYY-MM-DD"); console.log(dobDt) let age = getAge(dobDt) console.log(age) if(age < 18){ showUnderAge.value.isVisible = true; showContainer.value.isVisible = false; }else{ // Country Kick Out console.log(values.country) if(values.country !== "United States"){ showOutOfCountry.value.isVisible = true; showContainer.value.isVisible = false; console.log(showContainer) return; }else{ // Last Step if (currentStep.value === 3) { console.log("Done: ", JSON.stringify(formValues, null, 2)); return; } // accumlate the form values with the values from previous steps Object.assign(formValues, values); console.log("Current values: "); console.log(JSON.stringify(formValues, null, 2)); currentStep.value++; } } } function prevStep() { if (currentStep.value <= 0) { return; } currentStep.value--; } return { currentStep, currentSchema, prevStep, formValues, nextStep, showContainer, showOutOfCountry, showUnderAge }; }, }; </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } .appContainer{ max-width: 800px; margin: 30px auto; overflow: auto; min-height: 300px; padding: 30px; border-radius: 5px; border-style: solid; border-width: 1px; border-color: rgb(109, 109, 109); } label{ font-weight: bold; } .validationErrors{ color: red; font-weight: bold; } </style>