โœ… Form Validation for Vue.js

Overview

codecov circleci CDNJS npm npm Bundle Size Average time to resolve an issue Percentage of issues still open


vee-validate is a form validation library for Vue.js that allows you to validate inputs and build better form UIs in a familiar declarative style or using composition functions

Features

  • ๐Ÿž Easy: Declarative validation that is familiar and easy to setup
  • ๐Ÿง˜โ€โ™€๏ธ Flexible: Synchronous, Asynchronous, field-level or form-level validation
  • โšก๏ธ Fast: Build faster forms faster with intuitive API and small footprint
  • ๐Ÿ Minimal: Only handles the complicated and painful form concerns, gives you full control over everything else
  • ๐Ÿค Tiny: Small footprint < 5kb which makes your apps faster to load
  • ๐Ÿ˜Ž UI Agnostic: Works with native HTML elements or your favorite UI library components
  • ๐Ÿฆพ Progressive: Works with any setup whether you use Vue.js as a progressive enhancement or in a complex setup
  • โœ… Built-in Rules: Companion lib with 25+ Rules that covers most needs in most web applications
  • ๐ŸŒ i18n: 45+ locales for built-in rules contributed by developers from all over the world

Getting Started

Installation

# install with yarn
yarn add vee-validate@next

# install with npm
npm install vee-validate@next --save

Vue version support

The main v4 version supports Vue 3.x only, for previous versions of Vue, check the following the table

vue Version vee-validate version Documentation Link
2.x 2.x or 3.x v2 or v3
3.x 4.x v4

Usage

Declarative Components (Recommended)

Higher-order components are better suited for most of your cases. Register the Field and Form components and create a simple required validator:

import { Field, Form } from 'vee-validate';

export default {
  components: {
    Field,
    Form,
  },
  methods: {
    isRequired(value) {
      return value ? true : 'This field is required';
    },
  },
};

Then use the Form and Field components to render your form:

<Form v-slot="{ errors }">
  <Field name="field" :rules="isRequired" />

  <span>{{ errors.field }}</span>
</Form>

The Field component renders an input of type text by default but you can control that

Composition API

If you want more fine grained control, you can use useField function to compose validation logic into your component:

import { useField } from 'vee-validate';

export default {
  setup() {
    // Validator function
    const isRequired = value => (value ? true : 'This field is required');
    const { value, errorMessage } = useField('field', isRequired);

    return {
      value,
      errorMessage,
    };
  },
};

Then in your template use v-model to bind the value to your input and display the errors using errorMessage:

<input name="field" v-model="value" />
<span>{{ errorMessage }}</span>

๐Ÿ“š Documentation

Read the documentation and demos.

Contributing

You are welcome to contribute to this project, but before you do, please make sure you read the contribution guide

Credits

Emeriti

Here we honor past contributors and sponsors who have been a major part on this project.

โš–๏ธ License

MIT

Comments
  • Prevent creation of $validator on every component.

    Prevent creation of $validator on every component.

    Versions:

    • VueJs: 2.3.2
    • Vee-Validate: 2.0.0-rc.3

    Description:

    In the beforeCreate() hook of the vee-validate mixin, a $validator object is created for every component in Vue.

    I think this is a bit excessive, and would like to propose that instead it is created only when needed, through a computed property that creates it on the fly on the first use. That way, only the components that use validation need to create this property. In my app, that's maybe about 5% of the used components.

    mixin.js:

    import Validator from './validator';
    
    export default (Vue, options) => ({
      computed: {
        $validator() {
          const validator = new Validator(null, { init: false });
          Vue.util.defineReactive(validator, 'errorBag', validator.errorBag);
          Vue.util.defineReactive(validator, 'fieldBag', validator.fieldBag);
          validator.init();
          return validator;
        },
        [options.errorBagName]: {
          get() {
            return this.$validator.errorBag;
          }
        },
        [options.fieldsBagName]: {
          get() {
            return this.$validator.fieldBag;
          }
        }
      }
    });
    
    

    I haven't tested this yet but am fairly certain that it should work. I am happy to do the testing and create a PR if it's welcome.

    โœจ enhancement 
    opened by lehni 58
  • ๐Ÿ“ข Please Read VeeValidate 3.0 docs before creating new issues

    ๐Ÿ“ข Please Read VeeValidate 3.0 docs before creating new issues

    The new documentation has replaced the old one, These are some links that will help you understand the changes:

    • docs: https://logaretm.github.io/vee-validate/
    • discussion issue: #2191

    The new release introduced breaking changes, I hope everyone has the patience to go through the documentation carefully.

    ๐Ÿ—ฏ discussion 
    opened by logaretm 36
  • vue-test-utils > 1.0.0-beta.12 fails with vee-validate

    vue-test-utils > 1.0.0-beta.12 fails with vee-validate

    Versions:

    • VueJs: 2.5.13
    • Vee-Validate: 2.0.6
    • vue/cli-plugin-unit-jest: 3.0.0-beta.6
    • vue/cli-service: 3.0.0-beta.6
    • vue/test-utils: 1.0.0-beta.10

    Description:

    Hi. I am having some trouble mounting a component which validate a custom component with Jest and Vee-Validate. When I am not unit testing, the components and validations work great. Having those errors when running my test:

    [Vue warn]: Error in config.errorHandler: "TypeError: Cannot set property '_error' of undefined"
    console.error node_modules\vue\dist\vue.runtime.common.js:1739
         RangeError: Maximum call stack size exceeded
    

    (more details at the end)

    Thank you very much in advance for your help.

    Steps To Reproduce:

    Here is the component I am unit testing, Step1.vue :

    <template>
      <div class="step1">
        <test name="POD"  v-model="testData" v-validate="'required'"></test>
        <p v-show="errors.has('POD')" class="is-error">{{ errors.first('POD') }}</p>
      </div>
    </template>
    
    <script>
      import test from "./test.vue"
    
      export default {
        data() {
          return {
            testData: "test"
          }
        },
        components: {
          test
        }
      }
    </script>
    

    Here is the custom component under vee-validation, test.vue :

    <template>
      <div>
        <p>{{currentValue}}</p><button @click="RemoveLetters">Remove letters</button>
      </div>
    </template>
    
    <script>
      export default {
        name: "test",
        props: ["value"],
        data() {
          return {
            currentValue: this.value,
          }
        },
        methods: {
          RemoveLetters: function () {
            this.currentValue = this.currentValue.substring(0, this.currentValue.length -2)
            this.$emit("input", this.currentValue)
          }
        }
      }
    </script>
    

    And here is my Step1.spec.js :

    import { mount, createLocalVue  } from "@vue/test-utils"
    import Component from "./Step1.vue"
    import VeeValidate from 'vee-validate'
    
    let localVue = createLocalVue()
    localVue.use(VeeValidate)
    
    describe("Step1.vue", () => {
      it("renders to a nice snapshot", () => {
        const wrapper = mount(Component, { localVue })
        expect(wrapper.html()).toMatchSnapshot()
      })
    })
    

    Error message:

    PASS  app\components\views\Step1\__tests__\Step1.spec.js
      โ— Console
    
        console.error node_modules\vue\dist\vue.runtime.common.js:589
          [Vue warn]: Error in config.errorHandler: "TypeError: Cannot set property '_error' of undefined"
        console.error node_modules\vue\dist\vue.runtime.common.js:1739
          TypeError: Cannot set property '_error' of undefined
              at errorHandler (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\@vue\test-utils\dist\vue-test-utils.js:4446:13)
              at globalHandleError (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:1725:34)
              at handleError (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:1719:3)
              at Array.<anonymous> (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:1837:9)
              at flushCallbacks (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:1756:14)
              at <anonymous>
        console.error node_modules\vue\dist\vue.runtime.common.js:589
          [Vue warn]: Error in nextTick: "RangeError: Maximum call stack size exceeded"
        console.error node_modules\vue\dist\vue.runtime.common.js:1739
          RangeError: Maximum call stack size exceeded
              at Watcher.cleanupDeps (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:3183:11)
              at Watcher.get (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:3154:10)
              at Watcher.run (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:3217:22)
              at Watcher.update (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:3205:10)
              at Dep.notify (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:695:13)
              at VueComponent.reactiveSetter [as $attrs] (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:1012:11)
              at updateChildComponent (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:2836:13)
              at prepatch (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:4142:5)
              at patchVnode (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:5923:7)
              at updateChildren (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:5820:9)
              at patchVnode (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:5934:29)
              at VueComponent.patch [as __patch__] (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:6094:9)
              at VueComponent.Vue._update (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:2668:19)
              at VueComponent.updateComponent (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:2786:10)
              at Watcher.get (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:3140:25)
              at Watcher.run (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:3217:22)
              at Watcher.update (D:\MUST\branches\11.0\SPAs\BookingOneStep\node_modules\vue\dist\vue.runtime.common.js:3205:10)
    
    ๐Ÿ™ help wanted โ˜” has workaround 
    opened by SwannLV 35
  • VeeValidate v3.0 ๐Ÿš€

    VeeValidate v3.0 ๐Ÿš€

    VeeValidate 3.0

    This is a draft implementation for version 3.0, which is mostly breaking in many ways but we will try to make it easier to migrate. The changes mostly affect directive usage and will have minimal effects on validation providers.

    This document details all the changes done in v3.

    You can follow the implementation PR here #2153

    You can test the v3 release with the vee-validate-edge npm package.

    Goals

    The goals of this release are as following:

    • Rewrite in TypeScript.
    • v-validate directive deprecation.
    • Overhaul the custom-rules/extension API.
    • Overhaul the localization API.

    TypeScript

    VeeValidate has been TypeScript-friendly for a very long time, but it had its shortcomings. Since it was maintained by contributors - a big shout out to you all - it often wasn't in sync with the actual code. Also, some typings were confusing because they were intended to be internal.

    A TypeScript codebase will not only give us more confidence, but it will also communicate the intent of this library APIs clearly to TypeScript/JavaScript users.

    Some aspects of vee-validate are impossible to Typecheck properly like the injected errors and fields. This is touched upon later.

    Directive Deprecation

    This is the biggest breaking change and will certainly have some backlash against it, the directive, after all, has been the primary way to use vee-validate since x.0 releases. Even vee-validate name is a pun for the v-validate directive.

    But to list the directive problems:

    • Requires global installation, tightly coupled to the rest of the library.
    • Directives do not have props, so to pass stuff around we use data-vv-* attributes which aren't reactive, are repetitive and will add clutter your template.
    • Forces injected state errors and fields to be present.
    • v-if and v-for caveats which aren't apparent to the developer at first glance.
    • Validation Scope is limited within a single component context, it doesn't carry the scope to nested and internal components.
    • Complicated grouping with the Scopes API which is often confused with Validation Scope, also adds clutter to your template.
    • Probably the only library that advertises the use of the Provider/Inject API which is not recommended for public use.
    • Templates can get out of hand and noisy really fast and that makes it harder to debug/maintain.

    Now a little bit of history, why was the directive the default design choice for this library?

    When vee-validate first got released for Vue 1.x the directives was more powerful back then. They had their own props, and they had their own state. Which means the directive was more like a pseudo-component, it was a great choice for this library's API because it did the job perfectly.

    When Vue 2.0 got released, it removed props and this from directives, I believe they were too powerful and a distinction had to be made between them and components, while directives offered a lower level access to the DOM it meant that they had to do less, yet I was stubborn and the API was left as is. I needed to implement external state management and resort to data-vv-* attributes. It wasn't very clean but it did the job again so the API remained the same, and because we had no better way of doing template based validation, it was fine.

    Then scoped-slots came out, and it took a while for me to properly understand how they can be used to run validation, remember what I said about directives? well, components while "high-level", they offer "low-level" access to Vue's virtual DOM. Which is what I needed exactly and what was missing for the directive.

    Now I'm going to talk about the biggest problems with the directive.

    Injected State

    The need for the injected state is caused by directives being stateless, as they don't have this and no longer can store stuff on their own. This change was introduced in Vue 2.0 release which was the biggest limitation introduced to directives.

    The primary way to use v-validate directive is to get your errors off an injected global state called errors, this causes a problem for maintenance sake as it is not immediately clear where did errors come from, which is the same downsides for using global mixins. Your teammates simply had to know that the project is using vee-validate.

    Being a globally present state, it has poor performance as it changes frequently depending on how many fields are reading/writing to that state. This can be observed if you have 100+ fields on the same page, which while is very rare it still meant that by default vee-validate wasn't performant.

    they are impossible to type check properly without breaking somebody's code out there.

    That leaves us with one option: Use mapState like a helper to explicitly inject state, very much like vuex. I originally intended for the directive to be in v3 and introduced a full-rewrite that implements that. But the API was unwieldy in my opinion and it didn't solve the performance issue, in fact, it made it worse.

    v-if and v-for caveats

    The directive life-cycle methods work most of the time, but when Vue decides to re-use a field to save up rendering time, The directive doesn't get notified in any way. Meaning if the directive was to pick up changes in the template it had to re-check the field it is being attached to every single time before validation, which degrades performance even further as observed in the test implementation I talked about earlier.

    Directives weren't meant to be dependent on the identity of the element they are being attached to, they should be dependent solely the expression and the directive args/modifiers configured for it. Which is what was missing for my initial understanding of directives.

    Sharing state between components

    Using inject API for sharing state between a parent component and a child component being validated wasn't very intuitive, also the confirmed rule and any cross-field rule would never work across components as they rely on the refs present in the context of the v-validate usage.

    This problem comes up weekly, and while we could argue the docs can do a better job to describe this issue, I think by trying to address many caveats it means that the API isn't that good in the first place.

    Scope API

    the data-vv-scope API was just ugly, confusing and was redundant most of the time. I personally never used it, and my team at Baianat rarely did and it rarely comes up in issues, which is an indication that it is underused, that means developers did not have multiple forms in the same component that often.

    Aside from looks, it also had a hand in performance degradation, because while maybe.field can be a name for a field called literally "maybe.field" or it could be a field scoped within a "maybe" scope name. That means that every time errors.first and errors.has are used, a lot of computation has to be done to determine which case is it. Another smell for bad API.

    And since directives do not have access to the rendering phase, it meant that they had no way to prepare some stuff beforehand. For example, to access field flags you need to always check for the field existence first:

    fields.name && fields.name.valid
    

    Which is annoying in large forms but there is no way around that, I tried playing around with Proxies, but they cannot be poly-filled and messed up big time with Vue.js dev-tools.

    The validator API was a mess

    There were actually two validator classes present, one injected in each component and the other would be the one you normally import from vee-validate and the two had identical public API but it was a mess. for example, validate and validateAll did the exact same thing. validateScopes was just an added confusion, another smell for a bad API.

    The alternative

    One of the goals of this release is to promote better practices, that meant less magic. So the directive had to go since it inherently promoted a few practices that are considered evil. You have been probably using vee-validate for your production site and it certainly did the job well, but did it feel elegant? There are two ways to make a simple API, it can be simple but crude or it can be simple as in elegant. I strive for the latter and I'm sure we all do.

    For the last few months, I have been advertising the use of ValidationProvider and ValidationObserver components recently whenever anyone faces one of the above problems. They will be the primary way to use v-validate as of the time of this writing. The other way that can be introduced in the future if Vue.js adds new APIs to be built upon like the function API if it made sense.

    At first, glance, using the ValidationProvider is more verbose, but when refactored properly they are much more productive and flexible than the directive. Also, the component API is very powerful and can allow some "magic" to happen. For example, the ValidationObserver can pick up ValidationProvider instances no matter how deeply nested they are and even if they are being used internally by other components. That means the Observer is able to correctly represent the state of forms.

    Since Observers can be nested, that solved the problem of scoping, as you can group fields together by observers and it is much more cleaner and clearer in the template than the old data-vv-scope API.

    They are superior in every way to the directive and having two APIs means the documentation would be splintered and one would have focused over the other, so the components API survived for being the better one.

    VeeValidate Global API

    VeeValidate has been re-written to expose a function-based API, this isn't a coincidence with the recent events in Vue.js community, it had been planned for a while.

    In short, The Validator, ErrorBag classes have been deprecated as they no longer were needed in favor of a new stateless API. So v3 exposes the following functions:

    • extend
    • localize
    • validate
    • configure
    • setInteractionMode
    • ValidationProvider
    • ValidationObserver
    • withValidation

    All of which are tree-shakable and more friendly to your bundle size.

    validate API

    Used to be the verify API, It is stateless, unlike the old Validator class, with this function you can run arbitrary validation for values using the vee-validate rule system and asynchronous validation pipeline with an i18n support without having to integrate components or anything in your project. Heck, you could even use it server-side, or if you are feeling a little rebellious you can use it inside other validation libraries like vuelidate.

    Common Uses for this are:

    • Vuex: as you might want to validate values in actions before committing them to the state.
    • Validating values rather than fields, which will come in handy if a certain Vue RFC is implemented ๐Ÿ˜‰.

    extend API

    Used to be the Validator.extend method.

    There are a few problems with the current rule system, especially for Date/Cross-field rules:

    • Date Validation is clunky and is dependent on date-fns implementation which lacks proper timezone support.
    • Fields can only target one field at a time which makes it impossible to cross-field-check multiple fields.
    • Value transformation/normalization before validation is usually needed, but is redundant if implemented as part of the rule.
    • Unnecessary increase to the footprint of vee-validate as date rules are rarely used, compared to required.
    • Impossible to pass objects reliably as rule parameters instead of an array.

    To fix this, date rules were deprecated, it is up to you to implement those rules and the new API will make it much easier. You can also use any JS date library you want, date-fns, moment, dayjs to name a few options.

    The value transformation/casting API allows you to prepare the value/params before validating. This plays nicely with cross-field validation, which will only transform a field vid to its value, this will be one of the few transformations available out of the box and will not be configurable.

    This is also handy when you want your field to emit a value of certain structure but want the custom validator to validate a certain aspect of that structure, for example you want to pass { value: 'xyz', id: 5 } to your model but you only want to validate the value prop.

    The proposed API looks like this:

    Validator.extend('rule', {
      validate (value, params) {
        // validate method, required if its a new rule, optional if already exists.
      },
      message (fieldName) {
        // message, optional.
      },
      params: [
        { name: 'paramName', isTarget: true }, // applies a locator transform to get the other field value.
        {
          name: 'otherParam',
          cast (value) {
            return new Date(value); // cast the param value before using it.
          }
        },
        // this param uses both transforms to locate the other field, then transforms its value.
        {
          name: 'complex',
          isTarget: true,
          cast (value) {
            return 'whatever'; // Cast the other field value
          }
        },
        immediate: false, // this rule should not trigger when the field is initially validated.
        computesRequired: false, // this rule can change the required state of this field.
      ]
    })
    

    Note that the isTarget prop on the rule itself has been deprecated.

    This is rather complex but it will be only used in complex rules. So it won't be used often. Also, it solves the object vs string param formatting, since in the string case it would be necessary to know the order of the params, but in objects, it is necessary to know the names of the params. when you provide a params array, it will always be passed as an object to your rule.

    It isn't required tho, you can still ignore the params array entirely and the params will be passed as-is to your rule, if you provide an object it will be passed as an object, same for the string syntax.

    Here is a snippet on how you would implement the after rule:

    import { extend } from 'vee-validate';
    import { parse, format, isValid, isAfter } from 'date-fns';
    
    extend('after', {
      validate (value, { other }) {
         const parsed = parse(value, 'some-date-format');
         if (!isValid(parsed)) return false;
    
         return isAfter(value, other);
      },
      // parse the field value.
      castValue: value => parse(targetValue, 'some-date-format', new Date(),
      params: [
        {
          name: 'other',
          isTarget: true,
          cast (targetValue) {
            // parse the target field value.
            return parse(targetValue, 'some-date-format', new Date());
          }
        }
      ]
    });
    

    Now its always guaranteed that other will be a date value and since you are parsing the value yourself in the validate function. It is very straightforward to implement complex rules like these.

    The extend function options are entirely optional. You can progressively extend and add more options or modify them in your rules during the life-cycle of your application.

    import { extend } from 'vee-validate';
    
    // A simpler shorthand for passing params.
    extend('ruleFn', {
      params: ['first', 'second'],
      // ... other stuff
    });
    
    // New rule without options and passing a validate function directly.
    extend('ruleFn', () => {
      return false;
    });
    
    
    // Add/Modify configuration for the rule.
    extend('ruleFn', {
      // options..
    });
    

    A11y

    VeeValidate offered basic accessibility features in v2 and in v3 it will go a step further.

    ariaInput

    The ValidationProvider slot props expose an ariaInput object which you can bind to your inputs:

    <template>
      <ValidationProvider rules="required" v-slot="{ aria }">
        <input type="text" v-model="value" v-bind="aria" />
        <pre>{{ aria }}</pre>
      </ValidationProvider>
    </template>
    
    <style>
    input.invalid {
      border: solid 1px red;
    }
    
    input.valid {
      border: solid 1px green;
    }
    </style>
    

    ariaMsg

    ariaMsg is another set of aria attributes, but you bind it to your error display element. A full example would look like this:

    <ValidationProvider rules="required" v-slot="{ errors, ariaInput, ariaMsg }">
      <div>
        <input type="text" v-model="values.classes" v-bind="ariaInput">
        <pre>{{ ariaInput }}</pre>
        <span v-bind="ariaMsg">{{ errors[0] }}</span>
      </div>
    </ValidationProvider>
    

    localize API and i18n

    The dictionary-based implementation for VeeValidate has been confusing to some, and in the Vue ecosystem, it was not widely used directly. For example, people opted often to use VueI18n since maintaining two validation APIs was problematic, it meant vee-validate had to provide its own adapter for VueI18n which is unnecessary kilobytes in the wire for those who use non-Node.js solutions for their SSR like PHP's Laravel.

    The new API has to be generic, it means the old dictionary had to be hidden away and used behind the scenes. It also means users should be able to have a way to use any i18n library they like.

    The localize function is an abstraction for the included simple dictionary, and its signature is identical to the Validator.localize method of the old API.

    import { localize } from 'vee-validate';
    
    localize('ar', {
      messages: {
        required: 'ู‡ุฐุง ุงู„ุญู‚ู„ ู…ุทู„ูˆุจ'
      }
    });
    

    The full dictionary looks like this:

    localize({
      en: {
        fields: {
          // custom messages for each field.
        },
        messages: {
          // messages for each rule.
        },
        names: {
          // custom field names.
        }
      }
    });
    

    Note that by default vee-validate does not install any locale or rules, you have to import what you need or opt-in to use the full build which has messages and rules loaded beforehand. but with extra footprint cost.

    The localize method is only useful if you plan to use the internal i18n dictionary used by vee-validate. But if you want to run your own solution like VueI18n you could do so while installing rules:

    import { extend } from 'vee-validate';
    import VueI18n from 'vue-i18n';
    import { required } from 'vee-validate/dist/rules';
    
    const i18n = new VueI18n({
      locale: 'en',
      messages: {
        en: {
          validation: {
            required: 'This field is required'
          }
        }
      }
    });
    
    extend('required', {
      ...required, // rule definition
      message (field, values) {
        return i8n.t('validation.required');
      }
    });
    

    Not importing the localize function will drop it from the bundle because its tree-shakable, and will reduce your bundle size down further.

    For convenience, vee-validate messages format was updated to be VueI18n compliant, for example:

    {
      max: `The {_field_} may not be greater than {length} characters.`,
      max_value: `The {_field_} must be {max} or less.`,
      mimes: `The {_field_} must have a valid file type.`,
      min: `The {_field_} must be at least {length} characters.`,
      min_value: `The {_field_} must be {min} or more.`
    }
    

    With that being said, the message generator signature was changed to look like this:

    interface ValidationMessageGenerator {
      (field: string, values: { [k: string]: any }): string;
    }
    

    Which means params and data are now merged into the same object. A message now can be either a templated message like shown above or a function that returns a string. That means you can use any i18n implementation out there.

    Bundle-size

    Few rules were removed due to their size and they are very easy to implement:

    • url
    • ip
    • ip_or_fqn
    • credit_card
    • date_format
    • after
    • before
    • date_between
    • decimal (often confused with integer and digits)

    This means vee-validate no longer depends on validator.js and will allow you to use whatever version of validator.js to add the rules you need without conflicts from vee-validate internal copy of it.

    Some rules behavior has been changed:

    The email rule implementation was changed to a simpler regex pattern check, so it might be less accurate than v2 releases.

    The length rule will only check if the given string/iterable length matches a specific length that is provided, it will no longer allow max param to be passed.

    The rules represent about 4kb on their own, they will be excluded by default and you will need to import the rules your app will be using. There is a full bundle with all the rules pre-configured. This allows us to add more rules in the future without worrying about the bundle size as it has been the case with 2.x releases.

    The bundle size of vee-validate v3 has dropped significantly:

    | Default Bundle | 2.x size | 3.0-alpha size | |--------------------------|----------|----------------| | Disk | 136kb | 79kb | | Minified | 58.7kb | 21kb | | Minified + Gzipped | 16kb | 13kb |


    | Full Bundle | 2.x size | 3.0-alpha size | |--------------------|----------|----------------| | Disk | 350kb | 84kb | | Minified | 124kb | 32kb | | Minified + Gzipped | 31kb | 17kb |

    This means vee-validate is no longer costly and still offers many of the features that made it popular.

    About v2

    VeeValidate 2.x will still be maintained and checked for bugs, all critical issues will be fixed in a timely manner, but will receive slower updates for newer stuff.

    Migration

    There will be a migration guide detailing the changes and how to replace each feature with its new implementation.

    You can follow the progress here: #2153

    ๐ŸŒŸ feature ๐Ÿ—ฏ discussion ๐Ÿ’ฃ breaking 
    opened by logaretm 34
  • Once an input has been visible using v-if, it always validates it as part of the form even when hidden again.

    Once an input has been visible using v-if, it always validates it as part of the form even when hidden again.

    Versions:

    • VueJs: 2.0.3
    • Vee-Validate: beta17

    Description:

    Hi,

    I'll publish a jsfiddle if required, but perhaps you're already aware of this issue. I have form in which I have some items that I do not want to display using v-if tags.

    If the input has been shown once, and then has been hidden using v-if = false then it seems that vee-validate is still validating the hidden field. It work great as long as the input has been hidden from the page load, but once displayed, and hidden again, it continues validating it.

    Is this a known issue?

    Steps To Reproduce:

    opened by denjaland 31
  • Can't validate form with multiple child components

    Can't validate form with multiple child components

    Hi,

    In our app we have some fairly complex dynamic forms that have been broken down into multiple sub components and can be nested a few levels deep. We also currently using vuex too.

    I don't seem to be able to get all the components to validate when validateAll is called at the parent level. After having a look at the source code it looks like this only emits and listens on the same component.

    Is this something that we should currently be able to do or something that might be looked at in the future?

    Regards James

    opened by sproogen 29
  • [Vue warn]: Error in directive validate bind hook:

    [Vue warn]: Error in directive validate bind hook: "TypeError: Cannot read property '$scopedSlots' of undefined"

    Essentially, I'm just mounting a component that has children with v-validate prop on a test.

    Once I remove the v-validate prop from the children, the test passes just fine.

    Any idea why that happens?

    Edit:

    Reproducing is possible here: https://github.com/jourdanrodrigues/v-validate-issue. I'm having this issue on a MacOS Mohave and Ubuntu/Alpine (Docker) and VeeValidate 2.2.x.

    ๐Ÿค” needs reproduction 
    opened by jourdanrodrigues 28
  • Validating a non-existent field:

    Validating a non-existent field: "result". Use "attach()" first.

    Versions

    • vee-validate: 2.1.6
    • vue: 2.5.2

    Describe the bug So I am getting this error on my system "Uncaught (in promise) Error: [vee-validate] Validating a non-existent field: "result". Use "attach()" first." I don't know why I get this error. Also I am not getting this error for every field I use this.$validator.validate() on but only in the last step

    To reproduce Created this fiddle https://jsfiddle.net/f1uk3r/bnrpdg01/1/

    Expected behavior The error should not come and it should log "passed when clicked submit."

    ๐Ÿ› bug 
    opened by f1uk3r 27
  • Clear errors after form submition

    Clear errors after form submition

    Versions:

    • VueJs: 2.1.7
    • Vee-Validate: 2.0.0-beta.18

    Description:

    Once I submit the form I clear the fields and I want to clear the errors as well, but I'm having a hard time trying to do that.

    Steps To Reproduce:

    Form:

    <form role="form" class="form-horizontal" @submit.prevent="persistData">
                <legend>Supervisor & Deputy Requests</legend>
    
                <div class="form-group">
                    <label for="requesttype" class="col-sm-2 control-label">Request type</label>
                    <div class="col-sm-10">
                        <select v-model="form.requesttype" name="form.requesttype" id="requesttype" class="form-control"
                                data-vv-rules="required" v-validate.initial="form.requesttype">
                            <option value=""></option>
                            <option value="Option 01">Option 01</option>
                            <option value="Option 02">Option 02</option>
                        </select>
                        <span v-show="errors.has('form.requesttype')" class="text-danger">This field is required</span>
                    </div>
                </div>
                <div class="form-group">
                    <label for="userid" class="col-sm-2 control-label">User ID</label>
                    <div class="col-sm-10">
                        <input v-model="form.userid" name="form.userid" type="text" class="form-control" id="userid"
                               data-vv-rules="required"
                               v-validate.initial="form.userid">
                        <span v-show="errors.has('form.userid')" class="text-danger">This field is required</span>
                    </div>
                </div>
                <div class="form-group">
                    <label for="requestdescription" class="col-sm-2 control-label">Request description</label>
                    <div class="col-sm-10">
                        <textarea v-model="form.requestdescription" name="form.requestdescription" class="form-control"
                                  id="requestdescription" cols="30"
                                  rows="10" data-vv-rules="required"
                                  v-validate.initial="form.requestdescription"></textarea>
                        <span v-show="errors.has('form.requestdescription')"
                              class="text-danger">This field is required</span>
                    </div>
                </div>
    
                <button type="submit" class="btn btn-primary pull-right">Submit</button>
            </form>
    

    Persist data method:

                    let self = this
                    // Validate All returns a promise and provides the validation result.
                    this.$validator.validateAll().then(success => {
                        if (!success) {
                            // handle error
                            console.log('Error!')
                            return
                        }
                        axios.post('/static/api/SupervisorDeputyRequest/persistdata.php', queryString.stringify(self.form))
                            .then(res => {
                                self.form = {
                                    requesttype: '',
                                    userid: '',
                                    requestdescription: ''
                                }
                            })
    

    I want to clear the errors in the AJAX callback. This code is in a .vue file and vee-validate is being imported in the main.js file.

    opened by badcom 27
  • Validate doesn't work in v-for

    Validate doesn't work in v-for

    Versions:

    • VueJs: 2.1.10
    • Vee-Validate: 2.0.0-beta.22

    Description:

    v-validate doesn't work on 2.0.0-beta.22

    Steps To Reproduce:

    I prepared https://jsfiddle.net/hf96yxxy/4/ using 2.0.0-beta.22, when the Name is empty, shows no errors. It does show error on 2.0.0-beta.21, but it cannot parse the index

    ๐Ÿ› bug duplicate 
    opened by murpzhu 24
  • "Unexpected token export" when importing validation rules with Jest

    Versions

    • vee-validate: 3.0.4
    • vue: 2.6.10

    Describe the bug I've seen that this issue has already been opened for Nuxt (#2282, #2249, #2240) and that the solution in that case is documented. But I encounter it in a vue-cli app, using TS and Jest, and I struggled to make it work.

    To reproduce Steps to reproduce the behavior:

    1. create a CLI app with TS and Jest
    npx @vue/cli create vee-v3 -m npm --inlinePreset '{"useConfigFiles": true,"plugins": {"@vue/cli-plugin-typescript": {"classComponent": false},"@vue/cli-plugin-unit-jest": {}}}'
    
    1. install vee-validate
    npm install vee-validate --save
    
    1. add vee-validate/dist/rules to HelloWorld.vue
    import { extend } from 'vee-validate';
    import { required } from 'vee-validate/dist/rules';
    extend('required', required);
    
    1. run the unit tests
    npm run test:unit 
    

    throws:

    export { alpha$1 as alpha, alpha_dash, alpha_num, alpha_spaces, between, confirmed, digits, dimensions, email, excluded, ext, image, integer, is, is_not, length, max, max_value, mimes, min, min_value, numeric, oneOf, regex, required, required_if, size };
        ^^^^^^
    
        SyntaxError: Unexpected token export
    

    I tried to tweak jest.config.js but I'm still running into the issue... I tried several approches from https://github.com/facebook/jest/issues/2550 without success.

    Do you have a working configuration for this use-case? If so, it would be great to add it to the documentation.

    (But TBH it would be better to change the rules.js packaging to make the issue go away, and avoid contorsions with build/testing tools)

    โœจ enhancement 
    opened by cexbrayat 23
  • handleSubmit together with @click doesn't work with Chrome/Edge

    handleSubmit together with @click doesn't work with Chrome/Edge

    What happened?

    Hello Awad,

    I use handleSubmit and use @click in the submit button. It works with Firefox, but with Chrome/Edge only the click-event is triggered.

    Here is a draft:

    <template>
      <VeeForm
        v-slot="{ handleSubmit, meta: formMeta }"
        :validation-schema="schema"
        as="div"
      >
        <form
          class="needs-validation"
          novalidate=""
          @submit="handleSubmit($event, onFormSubmit)"
        >
          {{ formMeta }}
          ...
          <Field
            id="name"
            v-model="form.name"
            name="name"
            type="text"
          />
          <button
            type="submit"
            class="btn btn-primary"
            @click="test(formMeta.valid, formMeta.dirty)"
          >
           Submit
          </button>
        </form>
      </VeeForm>
    </template>
    
    <script>
    import { markRaw } from "vue";
    import { Field, Form as VeeForm } from "vee-validate";
    import { object, string } from "yup";
    
    export default {
      components: {
        VeeForm,
        Field,
      },
      data() {
        return {
          schema: markRaw(
            object().shape({
              name: string().required(),
            })
          ),
          form: {
            name: "",
          }
        };
      },
      methods: {
        test: function (valid, dirty) {
          if (valid && dirty) {
            console.log("valid");
          }
        },
        async onFormSubmit() {
          console.log("submit");
        },
      },
    };
    </script>
    

    Reproduction steps

    1. Click the submit button.
    2. The submit event never runs.

    ...

    Version

    Vue.js 3.x and vee-validate 4.x

    What browsers are you seeing the problem on?

    • [ ] Firefox
    • [X] Chrome
    • [ ] Safari
    • [X] Microsoft Edge

    Relevant log output

    Error: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received
    

    Demo link

    https://codesandbox.io/s/unruffled-rain-62clt7?file=/src/components/HelloWorld.vue

    Code of Conduct

    ๐Ÿค” needs reproduction 
    opened by ikreb7 1
  • feat: Better Yup and Zod typing with output types and input inference

    feat: Better Yup and Zod typing with output types and input inference

    This PR augments the support of yup and zod with advanced features to make full use of these libraries capabilities, while also opening the door for 3rd party integrations to have the same features.

    Input and Output types

    This PR introduces the concept of "Input" and "Output" types in a given form schema. For example, consider this yup schema:

    yup.object({
      email: yup.string().required().email(),
      password: yup.string().required()
    });
    

    Now while this schema validates that a given value has both email and password fields, The user may not enter them. Meaning there is a possibility where email and password are undefined until the user has started changing them. This is an "InputType".

    So the schema really makes sure it passes only when both fields satisfy their conditions. TypeScript-wise, it means both values are strings and exist. This is an "Output" type.

    What this PR does is allow useField and especially useForm to handle this kind of duality of form values by being able to infer both the input and output types from a given validation schema.

    This will be done by introducing a new helper called toTypedSchema which exists in @vee-validate/zod or the newly added @vee-validate/yup packages.

    This helper activates this typing inferences and does the following:

    • Figures out the input type for your form/field without you having to tell it, just provide a schema.
    • Figures out the output type that you will use in handleSubmit as it will be always the output type.

    Here is a sample of it with yup

    import { useForm } from 'vee-validate';
    import * as yup from 'yup';
    import { toTypedSchema } from '@vee-validate/yup';
    
    const schema = toTypedSchema(
      yup.object({
        email: yup.string().email(EMAIL_MSG).required(),
        password: yup.string().min(8, MIN_MSG),
      })
    );
    
    
    const { useFieldModel, values, handleSubmit } = useForm({
      validationSchema: schema,
    });
    
    • useFieldModel: Field names are automatically checked
    • values: will be an input type of the schema, so { email: string | undefined; password: string | undefined }
    • handleSubmit: the first argument will be an output type, so. { email: string; password: string }

    The same benefits are applied with Zod as well, as the old API has been deprecated in favor of the new toTypedSchema.

    import { useForm } from 'vee-validate';
    import * as zod from 'zod';
    import { toTypedSchema } from '@vee-validate/zod';
    
    const schema = toTypedSchema(
      zod.object({
        email: zod.string().email(EMAIL_MSG).min(1, REQUIRED_MSG),
        password: zod.string().min(8, MIN_MSG),
      })
    );
    
    const { useFieldModel, values, handleSubmit } = useForm({
      validationSchema: schema,
    });
    

    For both packages, you can also use toTypedSchema on single-field schemas.

    // zod
    const rules = toTypedSchema(zod.string().min(1, 'required').min(8));
    
    // yup
    const rules = toTypedSchema(yup.string().required().min(8));
    
    // value is inferred as `string | undefined` since it is an "Input" type.
    const { value, errorMessage } = useField('test', rules);
    
    

    Schema Processing

    Since yup and zod both offer value casting/transformation capabilities then it makes sense to make use of that.

    Initial thinking is values produced in handleSubmit as the first argument are the result of either libraries processing/casting.

    โœ” Issues affected

    closes #4019

    opened by logaretm 1
  • Providing invalid object doesn't cause meta.valid to be false

    Providing invalid object doesn't cause meta.valid to be false

    What happened?

    Providing invalid object doesn't cause meta.valid to be false but it still doesn't allow form submission. Expected: meta.valid be false

    Using object validation for a form:

    const schema = object({
      'Gender': object({
        value: string().required(),
      }).required(),
    })
    

    Form:

    <Form @submit="onSubmit" :validation-schema="schema">
        <Field v-slot="{ field, meta }" v-model="gender" name="Gender">
           {{ meta }}
        </Field>
      <button type="submit">Submit</button>
    </Form>
    

    Reproduction

    https://vue-vutksg.stackblitz.io/ When you click the submit button, meta.valid is true but the form doesn't get submitted. Expected behaviour is meta.valid to be false. After clicking "change to valid object" button, the form gets submitted. This is correct.

    Version

    Vue.js 3.x and vee-validate 4.x

    What browsers are you seeing the problem on?

    • [ ] Firefox
    • [X] Chrome
    • [ ] Safari
    • [ ] Microsoft Edge

    Relevant log output

    No response

    Demo link

    https://stackblitz.com/edit/vue-vutksg?file=src%2FApp.vue

    Code of Conduct

    ๐Ÿ› bug 
    opened by parsagholipour 1
  • Using global and local validators together

    Using global and local validators together

    Hi!

    It is now possible to use either global validators in string and object syntax, or local validators in functional syntax.

    <Field rules="required" />
    
    <Field
      :rules="[
        (value) => value || 'Error',
        (value) => value > 2 || 'Error 2',
      ]"
    />
    

    But is it somehow possible to use local and global validators together in :rules value? If not, then it would be cool to add such an opportunity, because personally in our project such a need arises often.

    <!-- Something like this -->
    <Field
      :rules="[
        'required',
        (value) => value || 'Error',
        (value) => value > 2 || 'Error 2',
      ]"
    />
    

    Thanks!

    โœจ enhancement 
    opened by sttrbl 1
  • Unable to trigger falsy response from validate() method

    Unable to trigger falsy response from validate() method

    What happened?

    I've recently been working with a team that has been using vee-validate for some time as part of a component library it's built.

    One of those components is a form-page that can contain various input types requiring validation, along with a button that calls a handleSubmit() method. What we've found is that the current simple implementation that is intended to emit an "error" event isn't 100% reliable, nor does it contain any data. That current implementation looks like this:

    methods: {
    /**
     * Sumit form if validation is successful
     */
        onSubmit() {
            this.validate()
                .then(() => this.$emit('submit'))
                .catch(() => this.$emit('error'));
        },
        /**
         * Tap into the ValidationObserver validate
         * method to check
         */
        async validate() {
            const { validate } = this.$refs.form;
            return await validate()
                ? Promise.resolve()
                : Promise.reject();
        }
    } 
    

    In our documentation site created using styleguidist, the emitted values are handled like this

    /* markup */
    <form-page
                back-button
                @submit="handleSubmit"
                @error="handleError"
                @back="handleBack"
            >
    
    /* VueJS */
    methods: {
        handleSubmit() {
        // eslint-disable-next-line no-console
            console.log('form submitted');
        },
        handleBack() {
        // eslint-disable-next-line no-console
            console.log('back button clicked');
        },
        handleError() {
        // eslint-disable-next-line no-console
            console.log('error returned');
        }
    }
    

    Currently, I can see that both the handleSubmit() and handleBack() methods do get called, and also am seeing, what I'm assuming are, vee-validate toast messages when an invalid entry is made into one of the child inputs.

    What I'm not able to do, is have the validate() method trigger the Promise.reject() method, and so emit the error event.

    Reading the description for the validate() method on the https://vee-validate.logaretm.com/v2/api/validator.html#methods page, I see the following, which indicates that either a truthy or falsy value could be returned depending on whether an input passes validation or not.

    Validates the matching fields of the provided descriptor. when validation is done, the Promise resolves a boolean indicating whether the selected was valid or not.

    So far, I don't appear able to trigger a falsy response though, and so, the Promise.reject() method.

    I've made an initial attempt at returning a little more data with the 'error' event, but this still exhibits the same issue with getting the validate() method to trigger the Promise.reject() one.

    Is there a way of triggering the reject response with validate() along these lines, or is that not the way to think about what it returns?

    /* VueJS */
    methods: {
    /**
     * Submit form if validation is successful
     */
        onSubmit() {
            this.validate()
                .then(() => this.$emit('submit'))
                .catch((errorMsg) => this.$emit('error', errorMsg));
        },
        /**
         * Tap into the ValidationObserver validate
         * method to check
         */
        async validate() {
            const { validate } = this.$refs.form;
            return await validate()
                ? Promise.resolve()
                : Promise.reject(new Error('Validation failed'))
                    .then(
                        () => {
                            // not called
                        },
                        (err) => {
                            return err.message; // Error message
                        }
                    );
        }
    } 
    

    Reproduction steps

    ...

    Version

    Vue.js 2.x and vee-validate 3.x

    What browsers are you seeing the problem on?

    • [X] Firefox
    • [X] Chrome
    • [ ] Safari
    • [X] Microsoft Edge

    Relevant log output

    n/a
    

    Demo link

    n/a

    Code of Conduct

    ๐Ÿค” needs reproduction 
    opened by christopherallanperry 2
Releases(v4.7.3)
  • v4.7.3(Nov 13, 2022)

  • v4.7.2(Nov 2, 2022)

  • v4.7.1(Oct 23, 2022)

  • v4.7.0(Oct 9, 2022)

    ๐Ÿ†• New Features

    Controlled values filtering #3924

    A good use-case is where you assign a bunch of values as initial values to your form but your inputs only control a few of them but it wasn't possible to extract these controlled values from all the values.

    v4.7 Lets you do that using a few ways:

    You can grab controlledValues from useForm result

    const { handleSubmit, controlledValues } = useForm();
    
    const onSubmit = handleSubmit(async () => {
      // Send only controlled values to the API
      // Only fields declared with `useField` or `useFieldModel` will be sent
      const response = await client.post('/users/', controlledValues.value);
    });
    

    Or use withControlled composed function:

    const { handleSubmit } = useForm();
    
    const onSubmit = handleSubmit.withControlled(async values => {
      // Send only controlled values to the API
      // Only fields declared with `useField` or `useFieldModel` will be sent
      const response = await client.post('/users/', values);
    });
    

    vee-validate marks fields which were created using useFieldModel or useField (and <Field />) as "controlled" and these would be the only values included in the previous samples.

    Explict form context option #3204

    Previously useField and <Field /> components used implicit injections to resolve the form context they are part of. This prevented having multiple form contexts within the same component with useForm since each call will take over the fields declared after.

    Now when declaring fields with useField you can pass form option explicitly to assign that field to that form:

    const form1 = useForm();
    const form2 = useForm();
            
    const field1 = useField('field', undefined, {
      form: form1,
    });
    
    const ield2 = useField('field', undefined, {
      form: form2,
    });
    
    Source code(tar.gz)
    Source code(zip)
  • v4.6.10(Sep 30, 2022)

    ๐Ÿ› Bug Fixes

    • Fixed using File constructor while in SSR (56663aa2e50d7aa285ca1cb22887c8e8b3f7fd3c)

    i18n ๐ŸŒ

    • Updated SK and CS language files to include missing rules thanks to @Liwoj #3936 #3937
    Source code(tar.gz)
    Source code(zip)
  • v4.6.9(Sep 19, 2022)

    ๐Ÿ› Bug Fix

    • Fixed an issue where resetForm would leave behind null or undefined in array fields after reset #3934 (1c016d93b367229644dca643931ef63bc6e433dc)
    Source code(tar.gz)
    Source code(zip)
  • v4.6.8(Sep 19, 2022)

    ๐Ÿ› Bug Fixes

    • Run validation if we skip checkbox value setting if event trigger should validate #3927 (#3930)
    • Fix File value instance equality checks #3911 (#3932)
    • Fix nested value change not triggering validation when validateOnValueUpdate is enabled #3926 (#3929)

    ๐Ÿ‘• TypeScript

    • Exposed RuleExpression type #3913 (cdaf22df04b42a68f55133ad3854aae9a7ad6953)
    Source code(tar.gz)
    Source code(zip)
  • v4.6.7(Aug 27, 2022)

    ๐Ÿ‘• TypeScript

    Allow generics types to be passed to GenericValidatorFunction which previously caused errors with simple snippets like this:

    function validator(value: string) {
      // ...
    }
    
    const { value } = useField('field', validator);
    

    ๐Ÿ› Bug Fixes

    • Fixed an issue with async function validators not respecting the last run error messages #3906 (#3908)
    Source code(tar.gz)
    Source code(zip)
  • v4.6.6(Aug 16, 2022)

  • v4.6.5(Aug 11, 2022)

    ๐Ÿ› Bug Fixes

    • Fixed an issue where checkboxes bound to an object could fail unchecking #3883 (#3885)
    • Fixed an issue with field's meta.dirty not being set correctly after calling resetField with a new value #3891 (#3892)
    Source code(tar.gz)
    Source code(zip)
  • v4.6.4(Aug 7, 2022)

    ๐Ÿ› Bug Fixes

    • Fixed an issue where useFieldModel did not trigger validation for nested paths (fbe273c6f2c5d30a1996777561eda2268d8a02e0)
    Source code(tar.gz)
    Source code(zip)
  • v4.6.3(Aug 7, 2022)

  • v4.6.2(Jul 17, 2022)

    ๐Ÿ‘• TypeScript

    • Expose FieldOptions and FormOptions interfaces #3843 (7437612ab554f8f65b445f7b065725b570a9a14a)

    ๐Ÿ› Bug Fixes

    • Avoid toggling field array checkboxes values when an item is removed #3844 (fffad4bea68cc949d0bce440b5daf43901aaca7f)
    Source code(tar.gz)
    Source code(zip)
  • v4.6.1(Jul 17, 2022)

  • v4.6.0(Jul 12, 2022)

    This release has been in the making for a while and I'm really glad it is finally released with a lot of requested improvements and new features.

    ๐Ÿ†• New Features

    v-model with FieldArray API

    You can now use v-model directive with any kind of input to mutate the field array value directly without having to use <Field /> or useField.

    <Form>
      <FieldArray name="users" v-slot="{ fields }">
        <div v-for="(field, idx) in fields" :key="field.key">
          <input v-model="fields[idx].value" />
        </div>
      </FieldArray>
      
      <button>Submit</button>
    </Form>
    

    Keep values after fields are unmounted

    By default, vee-validate destroys the form values automatically whenever a field is unmounted. This made creating tabbed forms or multi-step forms a little bit harder to achieve since you needed to implement a mechanism to track the values independently from vee-validate.

    Now there is a new (config available) (e6e1c1d) that allows you to control this behavior on the form and field levels.

    In the component API, you can pass keepValue or keepValues to <Field /> and <Form /> components respectively.

    <!-- Now all field will keep their values when unmounted unless specified otherwise -->
    <Form keep-values>
      <template v-if="showFields">
        <Field name="field" as="input" rules="required" />
        <!-- This field opts out and its value will be destroyed -->
        <Field name="[non-nested.field]" :keep-value="false" />
        <Field name="drink" as="input" type="checkbox" value="Tea" rules="required" /> Tea
      </template>
    
      <button>Submit</button>
    </Form>
    

    You can also pass keepValueOnUnmount and keepValuesOnUnmount to useField() and useForm() respectively:

    useForm({
     // default is false
      keepValuesOnUnmount: true
    });
    
    useField('field', undefined, {
      // default is whatever the form is configured to, if no form then `false`
      keepValueOnUnmount: true
    });
    

    Note Keep in mind that the field config takes priority over the form config if specified. Otherwise, all fields will follow the form's config.

    useFieldModel API

    A new useFieldModel function was added] to useForm which introduces a new way to use useForm without having to call useField.

    The reason for this is useField is meant to create input components, not model bindings. The useFieldModel allows you to create bindable refs that you can use directly with v-model on your components or any 3rd party components. This makes it significantly easier to integrate with 3rd party libraries.

    <template>
      <input name="email" v-model="email" />
      <span>{{ errors.email }}</span>
    
      <input name="password" v-model="password" type="password" />
      <span>{{ errors.password }}</span>
    </template>
    
    <script setup>
    import { useForm } from 'vee-validate';
    import MyTextInput from '@/components/MyTextInput.vue';
    
    // Define a validation schema
    const simpleSchema = {
      email(value) {
        // validate email value and return messages...
      },
      name(value) {
        // validate name value and return messages...
      },
    };
    
    // Create a form context with the validation schema
    const { errors, useFieldModel } = useForm({
      validationSchema: simpleSchema,
    });
    
    const email = useFieldModel('email');
    const password = useFieldModel('password');
    
    // or multiple models at once
    const [email, password] = useFieldModel(['email', 'password']);
    </script>
    

    This is much less verbose than useField and is optimized to be just a validatable model. However you will no longer have access to the advanced state and capabilities of useField like meta and validation triggers. So you will need to implement your own logic for when to show errors as they will be generated immediately whenever the value changes.

    Automatic v-model events with useField

    Quite often you will setup your component to support v-model directive by adding a modelValue prop and emitting a update:modelValue event whenever the value changes.

    If you use useField in your input component you don't have to manage that yourself, it is automatically done for you. Whenever the useField value changes it will emit the update:modelValue event and whenever the modelValue prop changes the useField value will be synced and validated automatically.

    The only requirement is you need to define your model prop on your component explicitly.

    <script setup>
    import { useField } from 'vee-validate';
    
    defineProps({
      // Must be defined
      modelValue: {
        type: String,
        default: '',
      },
    });
    
    const { value } = useField('field', undefined);
    </script>
    

    You can change the default model prop name by passing modelPropName option to useField:

    <script setup>
    import { useField } from 'vee-validate';
    
    defineProps({
      // Must be defined
      custom: {
        type: String,
        default: '',
      },
    });
    
    // component will now emit `update:custom` and sync `custom` prop value with the `value` returned from `useField`.
    const { value } = useField('field', undefined, {
      modelPropName: 'custom',
    });
    </script>
    

    You can also disable this behavior completely and manage those events yourself by passing syncVModel option to useField:

    <script setup>
    import { useField } from 'vee-validate';
    
    // Now it won't emit anything and won't sync anything
    const { value } = useField('field', undefined, {
      syncVModel: false,
    });
    </script>
    

    Other minor new features

    • Added move() to FieldArray (a52f133)
    • If you are using a native <input type="file"> element its value will now respect the multiple attribute, if it is present and set to true then it will be an array of files. Otherwise, it will be a single file. This could be a breaking change for some.

    ๐Ÿ‘• TypeScript Changes

    • Expose ValidationOptions type #3825 (9854865)
    • Exposed component APIs to their TS defs with refs #3292 (ae59d0f)
    • Remove yup type dependency (#3704) (e772f9a). This sadly loses the ability to infer the types from a yup schema, however it caused more errors than it is worth and introduced an installation dependency on yup even if it is not used.

    ๐Ÿ› Bug Fixes

    • Use multiple batch queues for both validation modes #3783 (6156603)
    • Compare form's meta.dirty based on original values than staged initials #3782 (f3ffd3c)
    • Avoid value binding for file type inputs #3760 (3c76bb2)
    • Added existing undefined path fallback for optional arrays #3801 (fd0500c)
    • Added argument order for digits rule inja.json#3780 (9385457)
    Source code(tar.gz)
    Source code(zip)
  • v4.5.11(Apr 10, 2022)

    ๐Ÿ› Bug Fixes

    • Ignored validation of fields during unmounting #3748 (3d49faa4101902c2e77aee0a2d43cd29b69f7b4e)

    ๐Ÿ†• New Features

    useField now allows the usage of array of functions instead of a single function to perform validation (https://github.com/logaretm/vee-validate/issues/3725) #3726 thanks to @gbaquedano

    const {
      value: value,
      errors: errors,
    } = useField(
      'field',
      [
        val => (val ? true : REQUIRED_MESSAGE),
        val => ((val as string)?.length >= 3 ? true : MIN_MESSAGE)
      ],
      { bails: false }
    );
    
    Source code(tar.gz)
    Source code(zip)
  • v4.5.10(Mar 8, 2022)

    ๐Ÿ› Bug Fixes

    • Fixed an issue with da.json locale which caused the JSON file to not parse correctly (94853105e0ca4f425a2c6b5bb7cea2233ec7480d)
    Source code(tar.gz)
    Source code(zip)
  • v4.5.9(Mar 8, 2022)

    ๐Ÿ› Bug Fixes

    • Set meta.validated for fields validated by the form API's validate (ad9fa9d853a8cabb26cdde04c20c07d4f2673aa4)

    ๐ŸŒ i18n

    • Updated locale for ko, ja, zh-CN, zh-TW (d5fc7325a943bd6e42d19fa0b6057648d689be80)
    Source code(tar.gz)
    Source code(zip)
  • v4.5.8(Jan 23, 2022)

    ๐Ÿ› Bug Fixes

    • Fixed a general issue when a field changes its name and has errors at the old name path #3664 (f736e62b1bb82f940d14d74a6d505c913c1c3dde)
    • Fixed an issue where FieldArray.swap function wasn't working when either indices had falsy values (40afbd9cc3fb3de71de3f6ebb0a1b2774d9018ff)
    Source code(tar.gz)
    Source code(zip)
  • v4.5.7(Dec 7, 2021)

    ๐Ÿ› Bug Fixes

    • Always ensure update:modelValue listener existing on field binding object #3583 (6a53e80525a9c38ce8851407b832bc8409c3f334)

    ๐ŸŒ i18n

    • Added Uzbek locale thanks to @akahon (#3601)
    Source code(tar.gz)
    Source code(zip)
  • v4.5.6(Nov 17, 2021)

    ๐Ÿ› Bug Fixes

    • Use watchEffect to calculate FormContext.meta instead of computed #3580 (e8729dc72d2a027a666515360c9537a62a8d46ad)

    As a result of this, there should be a performance improvement depending on the size of your forms

    ๐Ÿ‘• TypeScript

    • Corrected the typings for resetField #3568 (4e9460e3a4f51f4a78ddcdf17f7c3073f899404f)

    ๐ŸŒ i18n

    • Added missing Estonian locale messages and fixes by (#3584) @Tarinu
    Source code(tar.gz)
    Source code(zip)
  • v3.4.14(Nov 8, 2021)

  • v4.5.5(Nov 1, 2021)

    ๐Ÿ› Bug Fixes

    • Fixed an issue where singular checkboxes would be toggled when the form is reset #3551 (cad12ba7502af7268029930a9176d8e160efeef6)
    Source code(tar.gz)
    Source code(zip)
  • v4.5.4(Oct 20, 2021)

  • v4.5.3(Oct 20, 2021)

  • v4.5.2(Sep 30, 2021)

  • v4.5.1(Sep 29, 2021)

  • v4.5.0(Sep 26, 2021)

    ๐Ÿ†• New Features

    Field Arrays

    A long-requested feature is a proper way to handle field arrays. With this release you get two ways you can manage your array fields:

    • useFieldArray a composition API version. Read more in docs
    • <FieldArray /> a component API version. Read more in docs.

    Both have the same API, and they make managing those fields much easier.

    Invalid Submission Handler

    Another common request is the ability to handle invalid submissions, for example, you may want to scroll to the first invalid element.

    This is now possible with both <Form /> component and useForm composition function. Check the links for their documentation:

    Devtools Plugin

    vee-validate now ships with its VueDevtools plugin, this will be an invaluable tool to help you debug your forms and their validation state.

    This is the initial release for the plugin, so please report any bugs and suggest any improvements you can think of. ๐Ÿ™

    Check the guide page.

    ๐Ÿ’จ Performance Enhancements

    A partial re-write of vee-validate v4 fixed a long-standing performance issue that was reported here #3399

    ๐Ÿ’€ Breaking Changes

    handleInput is removed from useField after being deprecated since 4.3, you can use handleChange instead of handleInput as follows:

    const { handleChange } = useField('email', {
      validateOnValueUpdate: false
    });
    
    handleChange('value'); // updates the value and validates
    handleChange('value', false); // updates the value without validation
    
    // replace deprecated handleInput with custom one
    const handleInput = (val) => handleChange(val, false);
    

    Note that handleInput prop still exists in <Field /> scope slot. This is only for useField.

    Note: This release was a 2-month work in progress, so there aren't any bug fixes as 4.4.x was already being worked on in parallel to this release, so both 4.4.x and 4.5.0 contain the same bug fixes which won't be mentioned here in the release notes. Check the previous releases for more information.

    Source code(tar.gz)
    Source code(zip)
  • v3.4.13(Sep 16, 2021)

  • v4.4.11(Sep 11, 2021)

    ๐Ÿ› Bug Fixes

    • Fixed an issue where computed rules triggered validation before the field was explicitly validated (via event trigger or calling validate).
    Source code(tar.gz)
    Source code(zip)
Owner
Abdelrahman Awad
Frontend Engineer. I dabble in Vue.js, Nuxt.js and Node.js
Abdelrahman Awad
Simple, lightweight model-based validation for Vue.js

vuelidate Simple, lightweight model-based validation for Vue.js Sponsors Gold Silver Bronze Features & characteristics: Model based Decoupled from tem

Vuelidate 6.5k Jan 3, 2023
xaboy 4.6k Jan 3, 2023
:clipboard: A schema-based form generator component for Vue.js

vue-form-generator A schema-based form generator component for Vue.js. Demo JSFiddle simple example CodePen simple example Features reactive forms bas

VueJS Generators 2.9k Dec 27, 2022
:tada: A magical vue admin https://panjiachen.github.io/vue-element-admin

English | ็ฎ€ไฝ“ไธญๆ–‡ | ๆ—ฅๆœฌ่ชž | Spanish SPONSORED BY ๆดปๅŠจๆœๅŠก้”€ๅ”ฎๅนณๅฐ ๅฎขๆˆทๆถˆๆฏ็›ด่พพๅทฅไฝœ็พค Introduction vue-element-admin is a production-ready front-end solution for admin inter

่Šฑ่ฃค่กฉ 80.1k Dec 31, 2022
:eyes: Vue in React, React in Vue. Seamless integration of the two. :dancers:

vuera NOTE: This project is looking for a maintainer! Use Vue components in your React app: import React from 'react' import MyVueComponent from './My

Aleksandr Komarov 4k Dec 30, 2022
๐ŸŽ‰ ๅŸบไบŽ vite 2.0 + vue 3.0 + vue-router 4.0 + vuex 4.0 + element-plus ็š„ๅŽๅฐ็ฎก็†็ณป็ปŸvue3-element-admin

vue3-element-admin ?? ๅŸบไบŽ Vite 2.0 + Vue3.0 + Vue-Router 4.0 + Vuex 4.0 + element-plus ็š„ๅŽๅฐ็ฎก็†็ณป็ปŸ ็ฎ€ไป‹ vue3-element-admin ๆ˜ฏไธ€ไธชๅŽๅฐๅ‰็ซฏ่งฃๅ†ณๆ–นๆกˆ๏ผŒๅฎƒๅŸบไบŽ vue3 ๅ’Œ element-plu

้›ชๆœˆๆฌงๅทด 84 Nov 28, 2022
Jenesius vue modal is simple library for Vue 3 only

Jenesius Vue Modal Jenesius vue modal is simple library for Vue 3 only . Site Documentation Installation npm i jenesius-vue-modal For add modals in yo

ะั€ั…ะธะฟั†ะตะฒ ะ•ะฒะณะตะฝะธะน 63 Dec 30, 2022
A template repository / quick start to build Azure Static Web Apps with a Node.js function. It uses Vue.js v3, Vue Router, Vuex, and Vite.js.

Azure Static Web App Template with Node.js API This is a template repository for creating Azure Static Web Apps that comes pre-configured with: Vue.js

Marc Duiker 6 Jun 25, 2022
Mosha-vue-toastify - A light weight and fun Vue 3 toast or notification or snack bar or however you wanna call it library.

Mosha Vue Toastify A lightweight and fun Vue 3 toast or notification or snack bar or however you wanna call it library. English | ็ฎ€ไฝ“ไธญๆ–‡ Talk is cheap,

Baidi Liu 187 Jan 2, 2023
A plugin that can help you create project friendly with Vue for @vue/cli 4.5

vue-cli-plugin-patch A plugin that can help you create project friendly with Vue for @vue/cli 4.5. Install First you need to install @vue/cli globally

null 2 Jan 6, 2022
Veloce: Starter template that uses Vue 3, Vite, TypeScript, SSR, Pinia, Vue Router, Express and Docker

Veloce Lightning-fast cold server start Instant hot module replacement (HMR) and dev SSR True on-demand compilation Tech Stack Vue 3: UI Rendering lib

Alan Morel 10 Oct 7, 2022
JavaScript Survey and Form Library

SurveyJS is a JavaScript Survey and Form Library. SurveyJS is a modern way to add surveys and forms to your website. It has versions for Angular, jQue

SurveyJS 3.5k Jan 5, 2023
Termbase fรผr รœbersetung in Form eines Obsidian Vault

lang file-id authors date tags topics en 2ff3822a-cc5f-4474-ab4e-d097dcc3a215 [email protected] 2022-01-06 #needs_completion #readme #winos #setup Readme

null 2 Jan 8, 2022
๐Ÿ““ The UI component explorer. Develop, document, & test React, Vue, Angular, Web Components, Ember, Svelte & more!

Build bulletproof UI components faster Storybook is a development environment for UI components. It allows you to browse a component library, view the

Storybook 75.9k Jan 9, 2023
A Vue.js 2.0 UI Toolkit for Web

A Vue.js 2.0 UI Toolkit for Web. Element will stay with Vue 2.x For Vue 3.0, we recommend using Element Plus from the same team Links Homepage and doc

้ฅฟไบ†ไนˆๅ‰็ซฏ 53k Jan 3, 2023
The Intuitive Vue Framework

Build your next Vue.js application with confidence using Nuxt: a framework making web development simple and powerful. Links ?? Documentation: https:/

Nuxt 41.8k Jan 5, 2023
๐Ÿ‰ Material Component Framework for Vue

Supporting Vuetify Vuetify is a MIT licensed project that is developed and maintained full-time by John Leider and Heather Leider; with support from t

vuetify 36.2k Jan 3, 2023
๐Ÿ› ๏ธ Standard Tooling for Vue.js Development

Vue CLI Vue CLI is the Standard Tooling for Vue.js Development. Documentation Docs are available at https://cli.vuejs.org/ - we are still working on r

vuejs 29.6k Jan 4, 2023
๐Ÿ—ƒ๏ธ Centralized State Management for Vue.js.

Vuex ?? HEADS UP! You're currently looking at Vuex 3 branch. If you're looking for Vuex 4, please check out 4.0 branch. Vuex is a state management pat

vuejs 27.9k Dec 30, 2022