DEV Community

Clean Code Studio
Clean Code Studio

Posted on • Edited on

Vue Form Validation (Laravel Inspired)

Travis
npm downloads
npm license
PRs Welcome
dependencies
npm version
HitCount
Open Source Love svg1
Maintenance

waving that vuejs form introduction & purpose title That Vue Form

Vue Form AKA Vuejs Form Mission Statement For Building Vue Validation & Javascript Validated Forms


coffee icon vuejs form installation title Installation

NPM

npm install --save-dev vuejs-form
Enter fullscreen mode Exit fullscreen mode

Yarn

yarn add vuejs-form --save
Enter fullscreen mode Exit fullscreen mode

CDN

<script src='https://unpkg.com/vuejs-form@latest/build/vuejs-form.min.js'></script>
Enter fullscreen mode Exit fullscreen mode

Four Official Apis



Playground Examples



Vue Example One


Show First Error For Each Field And

Only Validate Form (AKA find errors) when Form Data is submitted

<template>
    <div>        
        <input type='text' v-model='form.name' />
        <span v-if="form.errors().has('name')" v-text="form.errors().get('email')"></span>

        <input type='email' v-model='form.email' />
        <span v-if="form.errors().has('email')" v-text="form.errors().get('email')"></span>

        <input type='password' v-model='form.password' />
        <span v-if="form.errors().has('password')" v-text="form.errors().get('password')"></span>

        <input type='password' v-model='form.password_confirmation' />
        <span v-if="form.errors().has('password_confirmation')" v-text="form.errors().get('password_confirmation')"></span>

        <hr>

        <button :disabled='form.empty()' @click='submit'>
            Complete
        </button>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode
import form from 'vuejs-form'

export default {
    data: () => ({
        form: form({
            email: '',
            password: '',
            password_confirmation: ''
        })
        .rules({
            email: 'email|min:5|required',
            password: 'required|min:5|confirmed'
        })
        .messages({
            'email.email': 'Email field must be an email (durr)',
            'password.confirmed': 'Whoops, :attribute value does not match :confirmed value',
        }),
   }),

    methods: {
        submit() {
            if (this.form.validate().errors().any()) return;

            console.log('submit: ', this.form.only('email', 'password'));
            console.log('submit: ', this.form.except('password_confirmation'));
        },
    }
}
Enter fullscreen mode Exit fullscreen mode

Vue Example Two


Show all form errors for all form fields

Re-validate Form Any time user updates form data for any field

<template>
    <div>
        <div v-if="form.errors().any()" v-for="(message, key) in form.errors().list()" :key="`${key}.error`">
            {{ message }}
        </div>

        <input type='email' v-model='form.email' /> <br>
        <input type='password' v-model='form.password' /> <br>
        <input type='password' v-model='form.password_confirmation' /> <br>

        <hr>

        <button :disabled='form.empty()' @click='submit'>
            Complete
        </button>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode
import form from 'vuejs-form'

export default {
    data: () => ({
        form: form({
            email: '',
            password: '',
            password_confirmation: ''
        })
        .rules({
            email: 'email|min:5|required',
            password: 'required|min:5|confirmed'
        })
        .messages({
            'email.email': ':attribute must be a valid email',
            'email.min': ':attribute may not have less than :min characters',
            'password.confirmed': 'Whoops, :attribute value does not match :confirmed value',
        }),
   }),

   watch: {
       /*--------------------------------------------------------------
        | When Should Your Form "Validate", Providing Error Messages?
        |--------------------------------------------------------------
        | 
        |   Form validates every time form data is updated. To
        |   display errors on form submit, remove watcher &
        |   move "this.form.validate()" over to submit()
        |
        */

        ['form.data']: {
            deep: true,
            immediate: false,
            handler: 'onFormChange'
        }
   },

    methods: {
        onFormChange(after, before) {
             this.form.validate()
        },

        submit() {
            return this.form.errors().any() ? this.failed() : this.passed();
        },

        failed() {
            console.log('errors: ', this.form.errors().all());
        },

        passed() {
            console.log('data: ', this.form.all());
            console.log('wrapped data: ', this.form.wrap('data'));
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Form API



Validator Api



Rules Api



Error Messages Api



Quick Vue Example


<template>
    <div>
        <div v-if="form.errors().any()" v-for="(message, key) in form.errors().list()" :key="`${key}.error`">
            {{ message }}
        </div>

        <input type='text' v-model='form.name' /> <br>
        <input type='email' v-model='form.email' /> <br>
        <input type='password' v-model='form.password' /> <br>
        <input type='password' v-model='form.confirm_password' /> <br>
        <hr>
        <button :disabled='form.empty()' @click='submit'>
            Complete
        </button>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode
import form from 'vuejs-form'

export default {
    data: () => ({
        form: form({
            email: '',
            password: '',
            confirm_password: ''
        })
        .rules({
            email: 'email|min:5|required',
            password: 'same:confirm_password',
            confirm_password: 'min:6|required',
        })
        .messages({
            'email.required': ':attribute is required',
            'email.email': ':attribute must be a valid email',
            'email.min': ':attribute may not have less than :min characters',
            'password.same': 'Whoops, :attribute does not match the :same field',
        }),
   }),

   watch: {
       /*--------------------------------------------------------------
        * When Should Your Form "Validate", Providing Error Messages?
        *--------------------------------------------------------------
        * Form validates every time form data is updated. To
        * display errors on form submit, remove watcher &
        * move "this.form.validate()" over to submit()
        *--------------------------------------------------------------
        */
        ['form.data']: {
            deep: true,
            immediate: false,
            handler: (now, old) => { this.form.validate(); },
        }
   },

    methods: {
        failed() {
            console.log('errors: ', this.form.errors().all());
        },
        passed() {
            console.log('data: ', this.form.all());
            console.log('wrapped data: ', this.form.wrap('data'));
        },
        submit() {
            return this.form.errors().any() ? this.failed() : this.passed();
        },
    }
}
Enter fullscreen mode Exit fullscreen mode

Validator Api


Form Register Rules

@SeeAvailableValidationRules

form(data).rules({
    name: 'required|min:4',
    link: 'required|url',
    category: 'required|within:blue,reg,green'
});
Enter fullscreen mode Exit fullscreen mode

Optionally Use Arrays Syntax Instead Of Pipes

form(data).rules({
    name: ['required', 'min:4'],
    link: ['required', 'url'],
    category: ['required', 'within:blue,reg,green']
});
Enter fullscreen mode Exit fullscreen mode

Form Customize Error Messages

  • All rules have global default error messages shown when rule fails validation.
  • Optionally, you are able to override the global defaults rule messages
  • Simply use the form(data).rules(set).messages({ '{field}.{rule}': 'custom message for failing rule on field' });
let data = { email: ['required', 'email'] }
form({ email: 'chad'}).rules({
    email: ['required', 'email']
})
.messages({
    'email.required': 'Email field is called email, needa make it an email (Hence Email Field Name, dont worry ~ we added validation just in case you forgot to make the email field an email)'
})
Enter fullscreen mode Exit fullscreen mode

Form Validator Instance

form(data).rules(options).messages(customMessages);

// form.validator().addMessage(field, error)
// form.validator().addRule(field, rules) 
// etc...
Enter fullscreen mode Exit fullscreen mode

Validate Form Data

  • Check current form data against associated form rules
  • IMPORTANT: form MUST call validate() method before retrieving current errors

COMMON GOTCHA!!!!

  • This wont get the current form errors
  • The form.validate() method was Never called
let data = { name: '' };
let rules = { name: 'required' };

form(data).rules(rules).errors().list();

// --------------------------------------------
// Form SHOULD fail, but errors list is empty
// --------------------------------------------
// Output: []
// --------------------------------------------
Enter fullscreen mode Exit fullscreen mode

What's the reason?

Retrieving errors before validating form data

would retrieve our error messages Api instance,
but it hasn't been filled with our forms error messages.

form.validate() compares form data against form rules, populating our form errors with failing rule messages.

Validate THEN resolve the errors (Using forms fluent api)

let data = { name: '' };
let rules = { name: 'required' };

form(data).rules(rules).validate().errors().list();
// Output: ['Name field is required']

// Again, we'll need to validate before retrieving our 
// errors to validate that the values passes our given rules
form.name = 'hello world';

form.errors().list();
// Output: ['Name field is required']

form.validate().errors().list();
// Output: []; 
Enter fullscreen mode Exit fullscreen mode

Fluently call validate() before calling errors() is simple and to the point.

At first, this may seem like a tedious extra step. Many may wonder why we don't simply auto-validate the data?

Reason for form.validate().errors() Instead of simply form.errors() triggering the validation.

  • Reactive frameworks may use errors() and the associated Error Messages Api (@See Form Error Messages Api)
  • Without providing the option for the end developer to determine when the form validates
  • Async requests, only validate once we've resolved some given data
  • Immediate display of errors (Not always wanted)
  • Option Open To Immediately show error messages (@See Vue Watcher Example)
  • Some other developers may only want to validate data on form submission
  • Many validation rules can be abstracted using the form Api to simply disable the ability to submit a button
  • EX: <button :disabled='form.empty()' @click='submit'> Done </button>
  • Then within submit() method simply run if (this.form.validate().errors().any()) return;
  • That allows the option to set up vuejs-form more like a traditional Form, and avoid many complexities that come along with maintaining the status of our reactive state
  • etc...

Form Has Validator

Determine if form has a validator instance attached to it

form.hasValidator(); // true or false
Enter fullscreen mode Exit fullscreen mode

Form Set Validator

  • Set Validator Instance
  • Optionally import the validator instance itself, and extend its functionality validator().macro(add_method, method).
  • Then use form macros to track the current step form.macro(add_method, method).
  • vuejs-validators.js Also has validator life cycle hooks documented that are available here, but only documented within vuejs-form.js. Very helpful for multi-step forms
const { form, validator } = require('vuejs-form');


form().macro('setSwitchableValidators', (first, second) => {
    this.toggleValidators = 
    this.toggleBetween = first
});

Enter fullscreen mode Exit fullscreen mode

Rules Api

Accepted Rule

The field under form must be yes, on, 1, or true. This is useful for validating "Terms of Service" acceptance.

Passing Accepted Rule

let data = { terms_of_service: 'no' };
let rules = { terms_of_service: 'accepted' };

// false
form(data).rules(rules).validate().errors().has('terms_of_service');
Enter fullscreen mode Exit fullscreen mode

Failing Accepted Rule

let data = { terms_of_service: null }
let rules = { terms_of_service: 'accepted' }

// true
form(data).rules(rules).validate().errors().has('terms_of_services');
Enter fullscreen mode Exit fullscreen mode

Alpha Rule

The field under form must be entirely alphabetic characters.

Passing Alpha Rule

let data = { letters: 'asdeddadfjkkdjfasdf' };
let rules = { letters: ['alpha'] };

// false
form(data).rules(rules).validate().errors().has('letters');
Enter fullscreen mode Exit fullscreen mode

Failing Alpha Rule

let data = { letters: '5-@'}
let rules = { letters: ['alpha'] }

// true
form(data).rules(rules).validate().errors().has('letters');
Enter fullscreen mode Exit fullscreen mode

Alpha Dash Rule

The field under form may have alpha-numeric characters, as well as dashes and underscores.

Passing Alpha Dash Rule

let data = { slug: 'user_name' };
let rules = { slug: ['alpha_dash'] };

// false
form(data).rules(rules).validate().errors().has('slug');
Enter fullscreen mode Exit fullscreen mode

Failing Alpha Dash Rule

let data = { words: 'hello world'}
let rules = { words: ['alpha_dash'] }

// true
form(data).rules(rules).validate().errors().has('words');
Enter fullscreen mode Exit fullscreen mode

Alpha Num Rule

The field under form must be entirely alpha-numeric characters.

Passing Alpha Num Rule

let data = { key: '4asdasdfe4d23545w634adf' };
let rules = { key: ['alpha_num'] };

// false
form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Alpha Num Rule

let data = { identifier: '1-asdf4adf_d_42'}
let rules = { identifier: ['alpha_num'] }

// true
form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Array Rule

The field under form must be a JS array.

Passing Array Rule

let data = { list: ['banana', 'broccoli', 'carrot'] };
let rules = { list: 'array' };

// false 
form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Array Rule

let data = { options: { name: 'hey world' } }
let rules = { options: 'array' }

// true
form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Email Rule

The given field value must be an email

Passing Email Rule

let data = { email: 'example@cleancode.studio' };
let rules = { email: ['email'] };

// false
form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Email Rule

let data = { email: 'asdfsdaf@.net'}
let rules = { email: ['email'] }

// true
form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Boolean Rule

  • Boolish form, not strict boolean check
  • Validates that field value is "truthy" or "falsy"
Truthy Falsy
1 0
"1" "0"
"on" "off"
"On" "No"
"ON" "OFF"
"yes" "no"
"Yes" "Off"
"YES" "NO"
true false
"true" "false"
"True" "False"
"TRUE" "FALSE"

Passing Boolean Rule

let data = { selected: 'Yes' };
let rules = { selected: ['boolean'] };

// false
form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Boolean Rule

form = { selected: null };
rules = { selected: ['boolean'] };

// true
form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Confirmed form Rule

  • {field} value must match {field}_confirmation value
  • Example password must match password_confirmation value to pass confirmed ruled > Passing Confirmed Rule

```js bash
let data = { password: 'secret', password_confirmation: 'secret' }
let rules = { password: 'confirmed' }

// false
form(data).rules(rules).validate().errors().any();




> Failing Confirmed Rule


```js bash
let data = { password: 'secret' };
let rules = { password: 'confirmed' };

// true
form(data).rules(rules).validate().errors().any();
form.password_confirmation = 'something_something';

// true
form.validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Passing Confirmed Rule Again

```js bash
form.password_confirmation = 'secret';

// false
form.validate().errors().any();





### Different form Rule
The given field value is different than another field value

> Passing Different Rule


```js bash
let data = { password: 'asdfasdfasdf', confirm_password: 'secret' };
let rules = { password: 'different:confirm_password' };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Different Rule

```js bash
let data = { password: 'secret', confirm_password: 'secret' }
let rules = { password: 'different:confirm_password' }

form(data).rules(rules).validate().errors().any();





### Digits Rule
The field under form must be numeric and must have an exact length of value.

> Passing Digits Rule


```js
let data = { amount: '10000' }
let rules = { amount: 'digits:6' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Digits Rule

let data = { amount: '10000' }
let rules = { amount: 'digits:4' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Digits Between Rule

The field under form must be numeric and have a length between the lower and upper limit defined.

Passing Digits Between Rule

let data = { amount: '10000' }
let rules = { amount: 'digits_between:4,6' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Digits Between Rule

let data = { amount: '10000' }
let rules = { amount: 'digits_between:3,5' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Distinct Rule

The field under form must be an array with no duplicate values.

Passing Distinct Rule

let data = { shopping_list: ['ham', 'eggs', 'milk', 'turkey'] }
let rules = { shopping_list: 'distinct' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Distinct Rule


let data = { shopping_list: ['ham', 'ham', 'eggs', 'milk', 'turkey'] }
let rules = { shopping_list: 'distinct' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Email Rule

The given field value must be an email

Passing Email Rule

let data = { email: 'example@cleancode.studio' };
let rules = { email: ['email'] };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Email Rule

let data = { email: 'asdfsdaf@.net'}
let rules = { email: ['email'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Ends With Rule

The field under form must end with one of the given values.

Passing Ends With Rule

let data = { name: 'sammie' };
let rules = { name: 'ends_with:sl,ie,asx' };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Ends With Rule

let data = { name: 5 };
let rules = { name: 'ends_with:sl,ie,asx' };

form(data).rules(rules).validate().errors().any();

form.setData({ name: 'azure' }).setRules({ name: 'ends_with:sl,ie,asx' })

form.validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Integer Rule

This form rule does not verify that the input is of the "integer" variable type, only that the input is a string or numeric value that contains an integer.

Passing Integer Rule

let data = { students: 25 }
let rules = { students: ['integer'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Integer Rule

let data = { students: 'yes' }
let rules = { students: ['integer'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

IP Rule

This form rule confirms that value is an IP address.

Passing IP Rule

  • "115.42.150.37"
  • "192.168.0.1"
  • "110.234.52.124"
  • "2001:0db8:85a3:0000:0000:8a2e:0370:7334" (Ipv6)

Failing IP Rule

  • "210.110" – must have 4 octets
  • "255" – must have 4 octets
  • "y.y.y.y" – the only digit has allowed
  • "255.0.0.y" – the only digit has allowed
  • "666.10.10.20" – digit must between [0-255]
  • "4444.11.11.11" – digit must between [0-255]
  • "33.3333.33.3" – digit must between [0-255]

IPv4 Rule

This form rule confirms that value is an IPv4 address.

Passing IPv4 Rule

  • "115.42.150.37"
  • "192.168.0.1"
  • "110.234.52.124"

Failing IPv4 Rule

  • "210.110" – must have 4 octets
  • "255" – must have 4 octets
  • "y.y.y.y" – the only digit has allowed
  • "255.0.0.y" – the only digit has allowed
  • "666.10.10.20" – digit must between [0-255]
  • "4444.11.11.11" – digit must between [0-255]
  • "33.3333.33.3" – digit must between [0-255]
  • "2001:0db8:85a3:0000:0000:8a2e:0370:7334" (Ipv6)

IPv6 Rule

This form rule confirms that value is an IPv6 address.

Passing IPv6 Rule

  • "2001:0db8:85a3:0000:0000:8a2e:0370:7334" (Ipv6)

Failing IPv6 Rule

  • "210.110" – must have 4 octets
  • "255" – must have 4 octets
  • "y.y.y.y" – the only digit has allowed
  • "255.0.0.y" – the only digit has allowed
  • "666.10.10.20" – digit must between [0-255]
  • "4444.11.11.11" – digit must between [0-255]
  • "33.3333.33.3" – digit must between [0-255]
  • "110.234.52.124"
  • "192.168.0.1"
  • "115.42.150.37"

Json Rule

The given field value must be a Json String

Passing Json Rule

let data = { content: JSON.stringify({ inspire: 'love' }) };
let rules = { content: 'json' };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Json Rule

let data = { content: 'fasdf' }
let rules = { content: 'json' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Max Rule

The given field must not be more than the defined maximum limit

Passing Max Limit Rule

let data = { password: 'secret' }
let rules = { password: 'max:10' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Max Limit Rule

let data = { password: 'secret'}
let rules = { password: 'max:4' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Min Rule

The given field must not be less than the defined minimum limit

Passing Min Limit Rule

let data = { password: 'secret' }
let rules = { password: 'min:6' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Min Limit Rule

let data = { password: 'secret'}
let rules = { password: 'min:8' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Not Regex Rule

The given field value must NOT match the regular expression pattern

Passing Not Regex Rule

let data = { email: 'ex.-fn' };
let rules = { email: ['not_regex:/^.+@.+$/i'] };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Not Regex Rule



let data = { email: 'example@gmail.com'}
let rules = { email: ['not_regex:/^.+@.+$/i'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Not Within Rule

The given field must NOT be "within" the comma delimited list of items

Passing Not Within Rule

let data = { language: 'PigLatin' }
let rules = { language: 'not_within:German,Spanish,English,Latin' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Not Within Rule

let data = { pencil: '2a'};
let rules = { pencil: 'not_within:notebook,pencil,2a,marker,sharpie,whiteboard' };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Number Rule

The given field must be a Number (Strict Typed Check). See Numeric For Looser Type Checking

Passing Number Rule

let data = { id: 15 };
let rules = { id: ['number'] };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Number Rule

let data = { id: '15'}
let rules = { id: ['number'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Numeric Rule

Determine if a value is numeric, or is a string that can properly represent a numeric

  • Numerical value, not strict number check
  • Automatically attempts to cast value to numerical value.
  • Validates that field value an integer, decimal, or bigInt.

Passing Numeric Rule

let data = { members: '25' }
let rules = { member: ['numeric'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Numeric Rule

let data = { members: 'yes' }
let rules = { member: ['numeric'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Phone Rule

The given field value must be a phone number

Passing Phone Rule

let data = { send_sms: ['555-555-5555'] }
let rules = { send_sms: ['phone'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Phone Rule

let data = { send_sms: '+(3) - 4 32'}
let rules = { send_sms: ['phone'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Phone Number Formats Within Testing Coverage

  • +61 1 2345 6789
  • +61 01 2345 6789
  • 01 2345 6789
  • 01-2345-6789
  • (01) 2345 6789
  • (01) 2345-6789
  • 5555555555
  • (555) 555 5555
  • 555 555 5555
  • +15555555555
  • 555-555-5555

(Any contributions welcome (vuejs-validators.js repo) for improving regex form patterns for current rules as well as adding new rules)

Regex Rule

The given field value must match the regular expression pattern

Passing Regex Rule

let data = { email: 'example@gmail.com' };
let rules = { email: ['regex:/^.+@.+$/i'] };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Regex Rule

let data = { email: 'ex.-fn'}
let rules = { email: ['regex:/^.+@.+$/i'] }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Required Rule

Validates that a given field exists and its value is set

Passing Required Rule

let data = { name: 'jules' };
let rules = { name: ['required'] };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Required Rule

let data = { name: '' };
let rules = { name: ['required'] };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Same form Rule

The given field value is the same as another field value

Passing Same Rule

let data = { password: 'secret', confirm_password: 'secret' }
let rules = { password: 'same:confirm_password' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Same Rule

```js bash
let data = { password: 'asdfasdfasdf', confirm_password: 'secret' };
let rules = { password: 'same:confirm_password' };

form(data).rules(rules).validate().errors().any();




### Starts With Rule
The field under form must start with one of the given values.

> Passing Starts With Rule


```js
let data = { name: 'sammie' };
let rules = { name: 'starts_with:joe,sam,tom' };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Starts With Rule

let data = { name: 5 };
let rules = { name: 'starts_with:sl,ie,asx' };

form(data).rules(rules).validate().errors().any();

form.setData({ name: 'azure' })
    .setRules({ name: 'starts_with:joe,sam,tom'})
    .validate()
    .errors()
    .any();
Enter fullscreen mode Exit fullscreen mode

String Rule

The given field value must be a String

Passing String Rule

let data = { name: 'sammie' };
let rules = { name: 'string' };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing String Rule

let data = { name: 54345  }
let rules = { name: 'string' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Url Rule

The given field value must be an http(s) url

Passing Url Rule

let data = { link: 'https://cleancode.studio' };
let rules = { link: 'url' };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Url Rule

let data = { link: 'httP/ope_type@.net'}
let rules = { link: 'url' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Within Rule

The given field must be "within" the comma delimited list of items

Passing Within Rule

let data = { name: 'Sam' }
let rules = { name: 'within:James,Boronica,Sam,Steve,Lenny' }

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Failing Within Rule

let data = { name: 'jake'};
let rules = { name: 'within:patricia,veronica,samuel,jeviah' };

form(data).rules(rules).validate().errors().any();
Enter fullscreen mode Exit fullscreen mode

Form Error Messages Api

form.errors() Methods

Any Errors

Determine if there are "any" errors (bool)

let data = { name: '' };
let rules = { name: 'required'};
form(data).rules(rules).errors().any();
Enter fullscreen mode Exit fullscreen mode
Output: true
Enter fullscreen mode Exit fullscreen mode

All Errors

Retrieve all errors within the errors object

let data = { name: '', email: '' };
let rules = { name: 'required', email: 'email|required' };

form(data).rules(rules).validate().errors().all();
Enter fullscreen mode Exit fullscreen mode
Output:

{
    name: [
        'name field is required'
    ],
    email: [
        'email field must be an email address',
        'email field is required'
    ]
}
Enter fullscreen mode Exit fullscreen mode

List Errors

Retrieve all errors within the errors object

let data = { name: '', email: '' };
let rules = { name: 'required', email: 'email|required' };

form(data).rules(rules).validate().errors().list();
Enter fullscreen mode Exit fullscreen mode
Output:

[
    'name field is required',
    'email field must be an email address',
    'email field is required'
]
Enter fullscreen mode Exit fullscreen mode

Set Errors

Set all errors

let data = { name: '' };
let rules = { name: 'required' };

form(data).rules(rules).validate();

form.errors().list(); 
// Output: ['name is a required field']

form.errors().set({ notice: ['set this random error message'] });
form.errors().list()
Enter fullscreen mode Exit fullscreen mode
Output: ['set this random error message']
Enter fullscreen mode Exit fullscreen mode

Forget Errors

Forget errors and reset them to empty

let data = { name: '' };
let rules = { name: 'required' };

form(data).rules(rules).validate().errors().list();
// Output: ['Name is a required field']

form.errors().forget();
form.errors().list();
Enter fullscreen mode Exit fullscreen mode
Output: []
Enter fullscreen mode Exit fullscreen mode

Has Error

Determine if a specific field has error messages

let data = { name: '', email: 'example@gmail.com' };
let rules = { name: 'required', email: 'email|required' };
form(data).rules(rules).validate();

form.errors().has('name');
form.errors().has('email');
form.errors().has('something_else');
Enter fullscreen mode Exit fullscreen mode
Output:
has name: true
has email: false
has something_else: false
Enter fullscreen mode Exit fullscreen mode

Get Error

Get first error message for a specific field

let data = { name: '' };
let rules = { name: 'required|min:3'};

form(data).rules(rules).validate().errors().get('name');
Enter fullscreen mode Exit fullscreen mode
Output: "Name is a required field"
Enter fullscreen mode Exit fullscreen mode

List Error

List errors for a specific field

let data = { name: '' };
let rules = { name: 'required|min:3'};

form(data).rules(rules).validate().errors().list('name');
Enter fullscreen mode Exit fullscreen mode
Output: ['name is a required field', 'name must be longer than 3 characters']
Enter fullscreen mode Exit fullscreen mode

Add Error

Add error message for a specific field

let data = { name: '' };
let rules = { name: 'required|min:3'};

form(data).rules(rules).validate().add(
    'name', 'four failures in a row. Two more failures before your locked out'
);

form.errors().list('name');
Enter fullscreen mode Exit fullscreen mode
Output: ['name is a required field', 'name must be longer than 3 characters', 'four failures in a row. Two more failures before your locked out']
Enter fullscreen mode Exit fullscreen mode

Set Error

Set error messages for a specific field

let data = { name: '' };
let rules = { name: 'required' };

form(data).rules(rules).validate().list('name');
Enter fullscreen mode Exit fullscreen mode
Output: ['name is a required field']
Enter fullscreen mode Exit fullscreen mode
form.errors().set('name', ['random messages', 'set on', 'the name field']);
form.errors().list('name');
Enter fullscreen mode Exit fullscreen mode
Output: ['random messages', 'set on', 'the name field']
Enter fullscreen mode Exit fullscreen mode

Forget Error

Forget error messages for a specific field

let data = { name: '' };
let rules = { name: 'required' };

form(data).rules(rules).validate().list('name');
Enter fullscreen mode Exit fullscreen mode
Output: ['name is a required field']
Enter fullscreen mode Exit fullscreen mode
form.errors().forget('name');
form.errors().list('name');
Enter fullscreen mode Exit fullscreen mode
Output: []
Enter fullscreen mode Exit fullscreen mode
  • [all](#all
  • [boolean](#boolean
  • [empty](#empty
  • [except](#except
  • [fill](#fill
  • [filled](#filled
  • [forget](#forget
  • [has](#has
  • [hasAny](#hasany
  • [input](#input
  • [keys](#keys
  • [macro](#macro
  • [make](#make
  • [missing](#missing
  • [only](#only
  • [set](#set
  • [toArray](#toarray
  • [wrap](#wrap

all()

The all method returns the underlying input object represented by the form:

form({ name: 'sarah', email: 'sarah@gmail.com' }).all();

// { name: 'sarah', email: 'sarah@gmail.com' }
Enter fullscreen mode Exit fullscreen mode

boolean(property)

The boolean method determines if the given field has a truthy or falsy values:

Truthy values: true, "true", "yes", "on", "1", 1

Falsy values: Everything else


const LoginForm = form({
    name: '',
    email: '',
    terms: ''
})

LoginForm.terms = true
LoginForm.boolean('terms') // true

LoginForm.terms = 'true'
LoginForm.boolean('terms') // true

LoginForm.terms = 'yes'
LoginForm.boolean('terms') // true

LoginForm.terms = 'on'
LoginForm.boolean('terms') // true

LoginForm.terms = "1"
LoginForm.boolean('terms') // true

LoginForm.terms = 1
LoginForm.boolean('terms') // true
Enter fullscreen mode Exit fullscreen mode

empty(one, two, three, ...)

The empty method determines if the input property exists but the value is empty:

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.empty('name') // false
ExampleForm.empty('name', 'email') // false

ExampleForm.empty('id') // true
Enter fullscreen mode Exit fullscreen mode

except(one, two, three, ...)

The except method grabs all of the inputs except the properties passed in:

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.except('id')
/**
 * { name: 'sarah', email: 'sarah@gmail.com' }
*/

ExampleForm.except('id', 'name')
/**
 * { email: 'sarah@gmail.com' }
 */
Enter fullscreen mode Exit fullscreen mode

View source on GitHub

fill({ key: value, keyTwo: valueTwo, etc... })

The fill method allows you to fill in new or empty values without overriding existing values:

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.fill({
    id: 2,
    name: 'tim',
    email: 'tim@gmail.com'
})

ExampleForm.all()
// { id: 2, name: 'sarah', email: 'sarah@gmail.com' }
Enter fullscreen mode Exit fullscreen mode

filled(propertyOne, propertyTwo, etc...)

The filled method determine if a value is filled (AKA not empty):

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.filled('id', 'name') // false
ExampleForm.filled('name', 'email') // true
Enter fullscreen mode Exit fullscreen mode

forget(propertyOne, propertyTwo, etc...)

The forget method will remove or "forget" a key value pair from the form input data

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.forget('id', 'name')
ExampleForm.all() // { email: 'sarah@gmail.com' }
Enter fullscreen mode Exit fullscreen mode

has(propertyOne, propertyTwo, etc...)

The has method will determine if a key exists within the form input data

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.has('id', 'name') // true
ExampleForm.has('something', 'id', 'name') // false
Enter fullscreen mode Exit fullscreen mode

hasAny(propertyOne, propertyTwo, etc...)

The hasAny method will determine if a key has any of the given properties within the form input data

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.hasAny('id', 'name') // true
ExampleForm.hasAny('something', 'id', 'name') // true
Enter fullscreen mode Exit fullscreen mode

input(property, default = false)

The input method will resolve a given input value or default to false. You can define a default as the second parameter

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.input('id') // false
ExampleForm.input('id', 1) // 1
ExampleForm.input('name', 'tim') // sarah
Enter fullscreen mode Exit fullscreen mode

keys()

The keys method will resolve an array of the input keys

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.keys() // ['id', 'name', 'email']
Enter fullscreen mode Exit fullscreen mode

macro(key, fn)

The macro method can be used to extend upon the form object:

import form from 'vuejs-form';

form().macro('count', () => {
    return this.keys().length;
});

form().macro('mapInto', into => {
    return this.toArray().reduce((accumulated, { key, value }) => ({
            ...accumulated,
            ...into(key, value)
        }),
    {});
});

const ExampleForm = form({
    email: 'example@gmail',
    password: 'secret',
});

ExampleForm.mapInto((key, value) => ({ [`example_form_${key}`]: value }));
// { example_form_email: 'example@gmail.com', 'example_form_password': 'secret' };

Enter fullscreen mode Exit fullscreen mode

View source on GitHub

make({ ... })

The make method will "make" a new form when used on the underlying class (With the proxy used on all forms)

import { VueForm } from 'vuejs-form'

const ExampleForm = VueForm.make({ id: '', name: 'sarah', email: 'sarah@gmail.com' })
ExampleForm.all() // { id: '', name: 'sarah', email: 'sarah@gmail.com' }
Enter fullscreen mode Exit fullscreen mode

missing(propertyOne, propertyTwo, ...)

The missing method will determine if the form is missing the following properties

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' })

ExampleForm.missing('id') // false
ExampleForm.missing('something') // true
ExampleForm.missing('name', 'email') // false
ExampleForm.missing('name', 'email', 'something') // true
Enter fullscreen mode Exit fullscreen mode

only(propertyOne, propertyTwo, ...)

The only method will return an object of "only" the input properties you defined

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' })

ExampleForm.only('name', 'email') // { name: 'sarah', email: 'sarah@gmail.com' }
ExampleForm.only('id', 'name') // { id: '', name: 'sarah' }
ExampleForm.only('id') // { id: '' }
Enter fullscreen mode Exit fullscreen mode

set({ key: value, keyTwo: valueTwo, etc... })

The set method allows you to set new and override previous values:

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.set({
    id: 2,
    name: 'tim',
    email: 'tim@gmail.com',
    password: 'secret',
})

ExampleForm.all()
// { id: 2, name: 'tim', email: 'tim@gmail.com', password: 'secret' }
Enter fullscreen mode Exit fullscreen mode

toArray()

The toArray method transforms the input into an array of key value pair objects:

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.toArray()
/**
    [
        { key: 'id', value: '' },
        { key: 'name', value: 'sarah' },
        { key: 'email', value: 'sarah@gmail.com' }
    ]
*/

Enter fullscreen mode Exit fullscreen mode

wrap(key)

The wrap method allows you to wrap the input within a given object key:

const ExampleForm = form({ id: '', name: 'sarah', email: 'sarah@gmail.com' });

ExampleForm.wrap('data')
/**
  {
    data: {
        id: '',
        name: 'sarah',
        email: 'sarah@gmail.com'
    }
  }
*/

Enter fullscreen mode Exit fullscreen mode

Extend Api


Extend and append functionality to just about every single major service this package provides

Extend Form Using Macros

const form = require('vuejs-form');

form().macro('shortcut', () => {
    return this.validate().errors().list();
});  

let example = form({ name: '' }).rules({ name: 'required' });

example.shortcut();
// Output: ['Name is a required field'];
Enter fullscreen mode Exit fullscreen mode

Extend Validator Using Macros

const { form, validator } = require('vuejs-form');

validator().macro('translate', ({ dictionary, locale }) => {
    if (!Object.keys(dictionary).includes(locale)) {
        console.warn(`Translation dictionary does not include passed ${locale}`);

        return this;
    } 

    const language = Object.keys(this.messages);
    const dictionary_words = key => Object.keys(dictionary[locale]).includes(key);
    language.filter(dictionary_words).forEach(key => { this.messages[key] = dictionary[`${locale}.${key}`] });

    return this;
});

let example = form({ name: '' }).rules({ name: 'required' });

let locale = 'ru';
let dictionary = { ru: { email: "Эл.почта" } };

example.validator().translate({ locale, dictionary });
Enter fullscreen mode Exit fullscreen mode

Extending: Custom Error Messages

Customize error messages for specific rules on any given field

  • Globally, each rule provides a default error message
  • Easily override rule's default error message
  • Simply pass 'messages' to our validator
  • Only override messages you want to
let data = { name: '', email: '' };

let rules = {
    name: ['min:3', 'max:12', 'string', 'required'],
    email: ['email', 'required']
};

let customMessages = {
    'name.min': 'Whoops! :attribute is less than :min characters',
    'name.required': 'Wha oh, doesnt look like there any value for your :attribute field',

    'email.email': 'Really? Email is called Email...it has to be an email...',
};

form(data).rules(rules).messages(customMessages).validate().errors().all();
Enter fullscreen mode Exit fullscreen mode

Extending: Custom Rules

Add Your Own Validation Rules

  • Easily add, or override, validation rules
  • Add a group of rules at a time
  • Add a single rule add a time

Extending: Custom Rules - Single Rule

form().validator().extend(rule_name, [message, rule])
``js
let example = form({ name: 'timmy' }).rules({ name: 'uppercase' });

example.validator().extend('uppercase', [
':attribute must be uppercase',
({ value, validator, parameters }) => value === value.toUpperCase(),
]);

// true
example.validate().errors().has('name');

// "Name must be uppercase"
example.errors().get('name');
`

Extending: Custom Rules - multiple rules

form.validator().extend({ first: [message, rule], second: [message, rule], etc... })
`js
let example = form({ name: '' }).rules({ name: ['required_with:last_name', 'required' ] });

example.validator().extend({
uppercase: [
':attribute must be uppercase',
({ value }) => value === value.toUpperCase(),
],
not_uppercase: [
':attribute must not be uppercase',
({ value }) => value !== value.toUpperCase()
],
required_without: [
':attribute is only required when form is missing :required_without field',
({ validator, parameters }) => !Object.keys(validator.data).includes(parameters[0])
],
required_with: [
':attribute is required with the :required_with field',
({ validator, parameters }) => Object.keys(validator.data).includes(parameters[0])
],
});
`

Extend Form Into Multi Step Form (Not tested, but good base to provide some ideas)

  • Not actually tested outside of these docs, but solid starting point

`html



Step {{ multi.steps().currentStep }} of {{ multi.steps().count() }}

    <!-- Pass form data as props, via vuex, emit event on any data change from all form field children, or if your safe wit it simply reference this.$parent.multi.steps().current from the child field. If you do so, don't plan on using the child component outside of multi-step forms. this.$parent is traditionally bad practice -->
    <component :is="multi.steps().current().getComponent()"></component>

    <button class="btn-default" v-if="multi.steps().hasPrev()" @click="multi.steps().prev()">
        Prev
    </button>

    <button class="btn-primary" :disabled='multi.steps().current().errors().any()' v-if="multi.steps().hasNext()" @click="multi.steps().next()">
        Next    
    </button>

    <button class="btn-success" :disabled='multi.steps().current().errors().any()' v-if="multi.steps().isLast()" @click="submit">
        Done
    </button>
</div>


`

`javascript

const MultiStep = function (form) {
this.sections = {};
this.currentStep = 0;

this.parent = function () {
    return form;
};

this.current = function () {
    if (this.has(this.currentStep)) {
        return this.get(this.currentStep);
    } else {
        console.error("No current step found");
    }
};

this.currentComponent = function () {
    return this.current().component_is
};
this.count = function () {
    return this.list().length;
};

this.travel = function (to) {
    if (this.has(to)) {
        this.currentStep = to;

        return this.current();
    } else {
        return console.error(`form step ${to} not found`);
    }
};

this.prev = function () {
    if (!this.isFirst()) {
        this.currentStep = this.currentStep - 1;

        return this.current();
    } else {
        console.error('already on the very first step')
    }
};


this.next = function () {
    if (!this.isLast()) {
        this.currentStep = this.currentStep + 1;

        return this.current();
    } else {
        console.log('last step')
    }
};

this.hasPrev = function () {
    return this.has(this.currentStep + 1);
};

this.hasCurrent = function () {
    return this.has(this.currentStep);
};

this.isFirst = function () {
    return this.hasCurrent() && !this.hasPrev()
};

this.isLast = function () {
    return this.hasCurrent() && !this.hasNext();
};

this.hasNext = function () {
    return this.has(this.currentStep + 1)
};

this.any = function () {
    const isEmpty = value => ([
        value === null || value === '',
        Array.isArray(value) && value.length === 0,
        typeof value === 'object' && Object.keys(value).length === 0
    ].includes(true));

    return !isEmpty(this.list());
};

this.has = function (group) {
    return Object.keys(this.sections).includes(group)
        && this.sections[group].length > 0
};

this.all = function () {
    return this.sections;
};

this.list = function (group = false) {
    return group
        ? this.sections[group]
        : Object.keys(this.sections)
            .map(group => this.sections[group])
            .reduce((list, groups) => [ ...list,  ...groups ], []);
};

this.get = function (group) {
    if (this.has(group)) {
        return this.sections[group][0];
    }
};

this.add = function(group, item) {
    this.sections[group] = Array.isArray(this.sections[group])
        ? this.sections[group]
        : [];

    this.sections[group].push(item);

    return this;
};

this.set = function (group, items = []) {
    if (typeof items === 'object') {
        this.sections = items;
    } else {
        this.sections[group] = items;
    }
};

this.forget = function (group) {
    if (typeof group === 'undefined') {
        this.sections = {};
    } else {
        this.sections[group] = [];
    }
};

};

const steppable = function (form = {}) {
return new MultiStep(validator);
};

form().macro('multiple', () => {
this.steppables = steppable(this);

this.steps = function () {
    return this.steppables;
};

this.first = function () {
    return this.steps().get('0')
}

this.last = function () {
    return this.steps().list(this.steps().count() - 1);
};

this.current = function () {
    return this.steps().current();
};


return this;

});

form().multiple().steps();

/** Use macro to extend form and append vue component instance to each form step **/
form().macro('hasComponent', () => typeof this.component_is !== 'undefined');
form().macro('getComponent', () => {
this.hasComponent() ? this.component_is : <template><div>No Component Registered On This Form Instance</div></template>
});

form().macro('is', (vue_instance) => {
this.component_is = vue_instance;

return this;

});

form().multiple().steps();

const { name_fields, password_fields, final_step } = require('./components/forms/steps/index.js');

let multi = form({}).multiple();

multi.steps().add(0,
form({
last_name: '',
first_name: ''
})
.rules({
last_name: ['required', 'min:3', 'string', 'different:first_name'],
first_name: ['required', 'min:3', 'string', 'different:last_name']
})
.messages({
'last_name.required': 'Last name is required',
'last_name.min': 'Last name may not be less than :min characters',
'last_name.different': 'Last Name must be different than first name',
'last_name.string': 'Last Name must be a string',
'first_name.required': 'First name is required',
'first_name.min': 'First name may not be less than :min characters',
'first_name.different': 'Last Name must be different than last name',
'first_name.string': 'First name must be of the string type'
})
.is(name_fields)
);

multi.steps().add(1,
form({
password: '',
password_confirmation: '',
})
.rules({
password: ['required', 'min:5', 'string', 'confirmed'],
})
.is(password_fields)
);

multi.steps().add(2,
form({ terms_of_service: '' })
.rules({ terms_of_service: 'accepted|required' })
.messages({
'terms_of_service.accepted': "Must accept terms of service before moving on",
'terms_of_service.required': "Must accept terms of service before submitting form",
})
.is(final_step)
);

export default {
name: 'multi-step-form',
data: () => ({ multi }),

methods: {
    submit() {
        let data = this.multi.steps().list().reduce((data, step) => ({ ...data, ...step.all() }), {});

        console.log('all data: ', form(data).all());
    }
}

};
`


Utilization


`js
import form from 'vuejs-form'

const LoginForm = form({
name: '',
email: '',
password: '',
})

LoginForm.name // ''
LoginForm.name = 'sarah'
LoginForm.name // 'sarah'

form({
name: '',
email: '',
password: '',
}).all() // { name: 'sarah', email: '', password: '' }
form({
name: '',
email: '',
password: '',
}).has('email', 'password') // true
form({
name: '',
email: '',
password: '',
}).has('email', 'something') // false
form({
name: '',
email: '',
password: '',
}).hasAny('email', 'something') // true
form({
name: '',
email: '',
password: '',
}).empty('email') // true
form({
name: '',
email: '',
password: '',
}).filled('email') // false
form({
name: '',
email: '',
password: '',
}).filled('name') // true
form({
name: '',
email: '',
password: '',
}).boolean('email') // false
form({
name: '',
email: '',
password: '',
}).only('email', 'name') // { email: '', name: '', }
form({
name: '',
email: '',
password: '',
}).except('password') // { email: '', name: '' }
form({
name: '',
email: '',
password: '',
}).input('password') // ''
form({
name: '',
email: '',
password: '',
}).input('email', 'example@gmail.com') // 'example@gmail.com'

LoginForm.fill({
name: 'tim',
email: 'tim@gmail.com',
password: 'secret'
})

LoginForm.all() // { name: 'sarah', email: 'tim@gmail.com', password: 'secret' }

LoginForm.set({
name: 'jamie',
email: 'jamie@gmail.com',
password: 'password'
})

LoginForm.all() // { name: 'jamie', email: 'tim@gmail.com', password: 'secret' }

LoginForm.keys() // ['name', 'email', 'password']

LoginForm.missing('verified') // true
LoginForm.missing('email') // false

LoginForm.toArray()
/**
[
{ key: 'name', value: 'jamie' },
{ key: 'email', value: 'tim@gmail.com' },
{ key: 'password', value: 'secret' }
]
*/

LoginForm.wrap('data')
/**
{
data: {
name: 'jamie',
email: 'tim@gmail.com',
password: 'secret'
}
}
*/

LoginForm.forget('password', 'email')
LoginForm.all() // { name: 'jamie' }

/**

  • When dealing with HTML elements like checkboxes, your application may receive "truthy" values that are actually strings. For example, "true" or "on". For convenience, you may use the boolean method to retrieve these values as booleans. The boolean method returns true for 1, "1", true, "true", "on", and "yes". All other values will return false:
  • Boolean checks for */ LoginForm.boolean('name') // false

LoginForm.terms = true
LoginForm.boolean('terms') // true
LoginForm.terms = 'true'
LoginForm.boolean('terms') // true
LoginForm.terms = 'yes'
LoginForm.boolean('terms') // true
LoginForm.terms = 'on'
LoginForm.boolean('terms') // true
LoginForm.terms = "1"
LoginForm.boolean('terms') // true
LoginForm.terms = 1
LoginForm.boolean('terms') // true

/** Anything else will return false Ex: */
LoginForm.terms = 'asdfsdf'
LoginForm.boolean('terms') // false
`

Extend Form Functionality

`js
import form from 'vuejs-form'

form().macro('count', () => {
return this.keys().length
})

form().macro('mapInto', into => {
// NOTICE: this.data is where the input object is actually stored

this.data = Object.entries(this.data).reduce((input, [key, value]) => ({
        ...input,
        ...into(key, value)
    }),
{});

return this

})

const extendedForm = form({
email: 'example@gmail',
password: 'secret',
})

form().macro((key, value) => ({ [key]: value.split('@') })).all()
/**

  • { email: ['example', 'gmail'], password: 'secret' } */ `

Contribute


PRs are welcomed to this project.
If you want to improve the vuejs-form library, add
functionality or improve the docs please feel free to submit a PR.


Code Of Conduct


The Clean Code Studio code of conduct is derived from Laravel code of of conduct. Any violations
of the code of conduct may be reported to Zachary Horton (zak@cleancode.studio)

  • Participants will be tolerant of opposing views.

  • Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.

  • When interpreting the words and actions of others, participants should always assume good intentions.

  • Behavior that can be reasonably considered harassment will not be tolerated.


Security Vulnerabilities


If you discover a security vulnerability within Clean Code Studio Packages Or Specifically within vuejs-form, please
send an e-mail to Zachary Horton via zak@cleancode.studio. All security vulnerabilities will be promptly addressed.


Change Log



Release 1.2.6


  • Beautified Docs A Bit

Release 1.2.5


  • Updated Cdn Documented Link Examples To Reference Latest Instead Of Specific Version

Release 1.2.4


  • Updated Purpose.md Documentation To Us Image Notepad Message

Release 1.2.3


  • Updated Change Log Release Link References
  • Updated Purpose.md Documentation To Us Image Notepad Message

Release 1.2.2


  • Updated Document Headers
  • Removed api.md section of Documentation
  • Removed bloated docs from setup.md
  • Added cdn installation and npm installation examples

Release 1.2.1


  • Updated Documentation To Start With "Purpose" Of Package
  • Removed Documentation Content From Header.md
  • Caught Change Log Up

Release 1.2.0


  • Documentation Updated
  • First Official Stable Release
  • Semantic Versioning Officially Supported

Release 1.1.1


  • CDN Setup
  • CDN Documentation Added
  • Added markdown.js for internal markup creation
  • Added Security Vulnerabilities Documentation
  • Added Versioning To Documentation
  • Added Code Of Conduct To Documentation
  • Extensive Documentation
  • Security Vulnerabilities Docs
  • Code Of Conduct Docs
  • Markdown Support Class
  • highlight.md
  • Versioning implementation documented

Release 1.1.0


  • "form.getErrors()" replaced with "form.errors()"
  • "form.getValidator()" replaced with "form.validator()"
  • "vuejs-validators" setup as dev dependency
  • "ValidatableForm" Export ~ (Ex: const { ValidatableForm } = require('vuejs-form'))
  • Default import is ValidatableForm (Ex: import form from 'vuejs-form' has validator || import { form } from 'vuejs-form' does not have validator)

Versioning


Vuejs-Form Will Implement Semantic Versioning

Starting (Friday, May 15, 2020)

Code Status Stage Rule Example Version
First release New Product Start with 1.0.0 1.0.0
Backward compatible bug fixes Patch Release Increment the third digit 1.0.1
Backward compatible new features Minor Release Increment the middle digit and reset last digit to zero 1.1.0
Changes that break backward compatibility Major Release Increment the first digit and reset middle and last digits to zero 2.0.0

License


MIT © Zachary Horton (Clean Code Studio)

Top comments (3)

Collapse
 
cleancodestudio profile image
Clean Code Studio

Codepen Playground Examples are provided :)

Vue Form Validators Example One: Validation On Form Submission
codepen.io/zhorton34/pen/zYvWZYz

Vue Form Validators Example Two: Validation On Form Data Changes
codepen.io/zhorton34/pen/xxwaYez

Collapse
 
brainor profile image
brainor-rus • Edited

Hello. Is it possible to use async custom rule for validating unique laravel rule (from database)?
I tried like this

this.form.validator().extend({
                        'unique':[
                        ':attribute must be unique',
                            async ({ value, validator, parameters }) =>  {
                            let parametersArray = parameters[0].split(',');

                            await axios
                                .post('/api/validator/unique', {table:parametersArray[0], field:parametersArray[1], value:value})
                                .then(response => {
                                    return true;
                                })
                                .catch(error => {
                                    return false;
                                });
                        }]
                    });
Enter fullscreen mode Exit fullscreen mode

But it doesn't work.

Collapse
 
cleancodestudio profile image
Clean Code Studio