Search code examples
vuejs3vee-validate

Vue with a form validator via CDN but can't render the form elements


I need to use Vue with a form validator via CDN but I can't render the form elements, the code below is a simple form with just one field in the input but Vue doesn't render the form element, I've already lost several hours trying to find it the problem.

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vee-validate"></script>
<div id="app">
    

    <Form @submit="onSubmit">
        <Field name="email" type="email" :rules="validateEmail"></Field>
        <ErrorMessage name="email"></ErrorMessage>
        <button>Sign up</button>
    </Form>


</div>

<script>
    const {ErrorMessage, Field, Form} = "vee-validate";

    const {createApp, ref} = Vue

    createApp({
        setup() {
        }, components: {
            Form,
            Field,
            ErrorMessage,
        },
        methods: {
            onSubmit(values) {
                console.log(values, null, 2);
            },
            validateEmail(value) {
                // if the field is empty
                if (!value) {
                    return 'This field is required';
                }
                // if the field is not a valid email
                const regex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
                if (!regex.test(value)) {
                    return 'This field must be a valid email';
                }
                // All is good
                return true;
            },
        },
    }).use(VeeValidate).mount('#app')
</script>


Solution

  • You are pretty much there, only few things are off:

    • vee-validate is not a plugin, remove the .use(VeeValidate)
    • The global object is VeeValidate (or window.VeeValidate), so you have to destructure from there instead of vee-validate:
    const {ErrorMessage, Field, Form} = VeeValidate;
    
    • If you want to use the original HTML as template, you have to take care of in-dom template caveats. So you cannot use Form, as it will end up as a regular <form> element, you have to rename it or use is="vue:Form", and you have to specify the other components in kebap case (error-message, etc.).

    Here it is in a snippet:

    const { createApp, ref } = Vue;
    const {ErrorMessage, Field, Form} = VeeValidate;
    
    const App = {
      components: {
          Form,
          Field,
          ErrorMessage,
      },
      methods: {
          onSubmit(values) {
              console.log(values, null, 2);
          },
          validateEmail(value) {
              // if the field is empty
              if (!value) {
                  return 'This field is required';
              }
              // if the field is not a valid email
              const regex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
              if (!regex.test(value)) {
                  return 'This field must be a valid email';
              }
              // All is good
              return true;
          },
      },
    }
    const app = createApp(App)
    app.mount('#app')
    <div id="app">
        <form is="vue:Form" @submit="onSubmit">
            <Field name="email" type="email" :rules="validateEmail"></Field>
            <error-message name="email"></error-message>
            <button>Sign up</button>
        </form>
    </div>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="https://unpkg.com/vee-validate"></script>