2018-02-01 01:20:29 +03:00
|
|
|
|
# Vue Formulate
|
|
|
|
|
---------------
|
2018-02-01 04:06:56 +03:00
|
|
|
|
[![Build Status](https://travis-ci.org/wearebraid/vue-formulate.svg?branch=master)](https://travis-ci.org/wearebraid/vue-formulate)
|
2018-02-01 05:52:10 +03:00
|
|
|
|
[![Current Version](https://img.shields.io/npm/v/vue-formulate.svg)](https://www.npmjs.com/package/vue-formulate)
|
|
|
|
|
[![License](https://img.shields.io/github/license/wearebraid/vue-formulate.svg)](https://github.com/wearebraid/vue-formulate/blob/master/LICENSE.txt)
|
2018-02-01 01:20:29 +03:00
|
|
|
|
|
|
|
|
|
### What is it?
|
|
|
|
|
|
2018-02-01 01:23:24 +03:00
|
|
|
|
Vue Formulate is a [Vue](https://vuejs.org/) plugin that exposes an elegant
|
2018-02-01 01:20:29 +03:00
|
|
|
|
mechanism for building and validating forms with a centralized data store.
|
|
|
|
|
|
2018-03-14 22:37:29 +03:00
|
|
|
|
### Show and tell
|
|
|
|
|
|
2018-11-20 19:51:32 +03:00
|
|
|
|
You'll find an easy to use example, in [the example directory](https://github.com/wearebraid/vue-formulate/tree/master/example)
|
2018-03-14 22:37:29 +03:00
|
|
|
|
as well as a live demo available at: [demo.vueformulate.com](https://demo.vueformulate.com).
|
|
|
|
|
|
2018-02-01 05:52:10 +03:00
|
|
|
|
### Get Started
|
2018-02-01 01:20:29 +03:00
|
|
|
|
|
2018-02-01 05:52:10 +03:00
|
|
|
|
#### Download
|
2018-02-01 01:20:29 +03:00
|
|
|
|
First download the `vue-formulate` package from npm:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
npm install vue-formulate
|
|
|
|
|
```
|
|
|
|
|
|
2018-03-14 22:37:29 +03:00
|
|
|
|
If you want to use ES6 features in your project
|
|
|
|
|
(and this readme assumes you do), then you'll also
|
|
|
|
|
need Babel:
|
2018-03-14 17:49:40 +03:00
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
babel-preset-env
|
|
|
|
|
babel-preset-stage-2
|
|
|
|
|
```
|
|
|
|
|
|
2018-03-14 22:37:29 +03:00
|
|
|
|
Many Vue/Vuex projects require Babel’s `stage-2` preset.
|
|
|
|
|
Best practice is to include a `.babelrc` in the project
|
|
|
|
|
root:
|
2018-03-14 17:49:40 +03:00
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
{
|
|
|
|
|
"presets": [
|
|
|
|
|
["env", { "modules": false }],
|
|
|
|
|
"stage-2"
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2018-02-01 05:52:10 +03:00
|
|
|
|
#### Installation
|
|
|
|
|
|
2018-02-01 01:20:29 +03:00
|
|
|
|
Install `vue-formulate` like any other vue plugin:
|
|
|
|
|
|
|
|
|
|
```js
|
2018-02-01 01:23:24 +03:00
|
|
|
|
import Vue from 'vue'
|
2018-02-01 01:24:58 +03:00
|
|
|
|
import formulate from 'vue-formulate'
|
2018-02-01 01:20:29 +03:00
|
|
|
|
|
|
|
|
|
Vue.use(formulate)
|
|
|
|
|
```
|
2018-02-01 05:52:10 +03:00
|
|
|
|
#### Vuex
|
|
|
|
|
`vue-formulate` needs to be linked to your vuex store. Vuex can be
|
|
|
|
|
configured as a single root store, or as namespaced modules and `vue-formualte`
|
|
|
|
|
can work with either setup.
|
|
|
|
|
|
|
|
|
|
**Vuex Module**
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
import {formulateModule} from 'vue-formulate'
|
|
|
|
|
|
|
|
|
|
export default formulateModule('namespace')
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Using a namespaced vuex module is the recommended installation method. Just be
|
|
|
|
|
sure to replace `'namespace'` with the namespace of your vuex module.
|
|
|
|
|
|
|
|
|
|
Additionally, when using a vuex namespace, you _must_ also pass the namespace
|
|
|
|
|
in the Vue plugin installation call:
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
Vue.use(formulate, {vuexModule: 'namespace'})
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Alternatively, you can install `vue-formulate`'s store elements to your vuex
|
|
|
|
|
root store:
|
|
|
|
|
|
|
|
|
|
**Root Store**
|
|
|
|
|
|
|
|
|
|
```js
|
2018-02-02 20:07:51 +03:00
|
|
|
|
import Vue from 'vue'
|
|
|
|
|
import Vuex from 'vuex'
|
|
|
|
|
import {formulateState, formulateGetters, formulateMutations} from 'vue-formulate'
|
|
|
|
|
|
|
|
|
|
Vue.use(Vuex)
|
2018-02-01 05:52:10 +03:00
|
|
|
|
|
|
|
|
|
const state = () => ({
|
2018-02-02 20:07:51 +03:00
|
|
|
|
// your own state data can live next to vue-formulate's data
|
2018-03-14 17:49:40 +03:00
|
|
|
|
// Note: formulateState is a curried function.
|
2018-02-01 05:52:10 +03:00
|
|
|
|
your: 'data',
|
2018-03-14 17:49:40 +03:00
|
|
|
|
...formulateState()()
|
2018-02-01 05:52:10 +03:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const getters = {
|
2018-02-02 20:07:51 +03:00
|
|
|
|
// Your own getters can live next to vue-formulate's getters
|
2018-02-01 05:52:10 +03:00
|
|
|
|
yourGetter (state) {
|
|
|
|
|
return state.your
|
|
|
|
|
},
|
|
|
|
|
...formulateGetters()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mutations = {
|
2018-02-02 20:07:51 +03:00
|
|
|
|
// Your own mutations can live next to vue-formulate's mutations
|
2018-02-01 05:52:10 +03:00
|
|
|
|
setYour (state, payload) {
|
|
|
|
|
state.your = payload
|
|
|
|
|
},
|
|
|
|
|
...formulateMutations()
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-02 20:07:51 +03:00
|
|
|
|
export default new Vuex.Store({
|
2018-02-01 05:52:10 +03:00
|
|
|
|
state,
|
|
|
|
|
getters,
|
|
|
|
|
mutations
|
2018-02-02 20:07:51 +03:00
|
|
|
|
})
|
2018-02-01 05:52:10 +03:00
|
|
|
|
```
|
2018-02-01 01:20:29 +03:00
|
|
|
|
|
|
|
|
|
### Usage
|
|
|
|
|
|
|
|
|
|
`vue-formulate` automatically registers two components `formulate` and
|
|
|
|
|
`formulate-element`. These two elements are able to address most of your form
|
|
|
|
|
building needs. Here's a simple example:
|
|
|
|
|
|
|
|
|
|
```html
|
2018-02-01 05:52:10 +03:00
|
|
|
|
<formulate name="registration">
|
|
|
|
|
<formulate-element
|
|
|
|
|
name="email"
|
|
|
|
|
type="email"
|
|
|
|
|
/>
|
|
|
|
|
...more formulate-elements
|
|
|
|
|
</formulate>
|
2018-02-01 01:20:29 +03:00
|
|
|
|
```
|
|
|
|
|
|
2018-02-01 05:52:10 +03:00
|
|
|
|
You can think of `<formulate>` elements a little bit like traditional
|
|
|
|
|
`<form>` tags. You _must_ wrap your `formulate-element` components
|
|
|
|
|
in a `<formulate>` component. The `formulate` component has a single
|
|
|
|
|
required prop `name` which creates the form’s key in the vuex store.
|
|
|
|
|
|
|
|
|
|
All `formulate-element` components nested inside a `<formulate>`
|
2018-03-14 01:58:24 +03:00
|
|
|
|
component will automatically commit mutations directly to the
|
2018-02-01 05:52:10 +03:00
|
|
|
|
store. The store becomes a live representation of all your form’s
|
|
|
|
|
values.
|
|
|
|
|
|
2018-03-14 01:58:24 +03:00
|
|
|
|
The `formulate-element` component is a powerful component which handles field
|
|
|
|
|
generation.
|
2018-02-01 05:52:10 +03:00
|
|
|
|
|
2018-02-01 01:20:29 +03:00
|
|
|
|
### Validation Rules
|
|
|
|
|
|
2018-03-14 01:58:24 +03:00
|
|
|
|
There are several built-in validation methods and you can easily add your own as well.
|
2018-02-01 01:20:29 +03:00
|
|
|
|
|
|
|
|
|
Rule | Arguments
|
|
|
|
|
----------|---------------
|
2018-02-01 18:49:27 +03:00
|
|
|
|
required | *none*
|
|
|
|
|
email | *none*
|
|
|
|
|
confirmed | confirmation field
|
2018-11-20 19:51:32 +03:00
|
|
|
|
number | *none*
|
2018-02-01 01:20:29 +03:00
|
|
|
|
|
2018-11-20 19:51:32 +03:00
|
|
|
|
You can add as many validation rules as you want to each `formulate-element`,
|
2018-02-01 05:52:10 +03:00
|
|
|
|
simply chain your rules with pipes `|'. Additional arguments can be passed to
|
|
|
|
|
validation rules by using parenthesis after the rule name:
|
2018-02-01 01:20:29 +03:00
|
|
|
|
|
|
|
|
|
```
|
2018-02-01 18:47:11 +03:00
|
|
|
|
validation="required|confirmed(confirmation_field)"
|
2018-02-01 01:20:29 +03:00
|
|
|
|
```
|
|
|
|
|
|
2018-03-14 01:58:24 +03:00
|
|
|
|
The field label used in built-in validation methods is the `validation-label`
|
2018-02-02 21:38:05 +03:00
|
|
|
|
attribute on your `formulate-element`. If no `validation-label` is found then
|
2018-02-01 18:47:11 +03:00
|
|
|
|
the `label` attribute is used, and if no `label` attribute is found it will
|
|
|
|
|
fall back to the field’s `name` attribute (which is required).
|
2018-02-01 05:52:10 +03:00
|
|
|
|
|
|
|
|
|
#### Custom Validation Rules
|
|
|
|
|
|
|
|
|
|
Validation rules are easy to write! They're just simple functions that are
|
|
|
|
|
always passed at least one argument, an object containing the `field` name,
|
2018-02-01 18:47:11 +03:00
|
|
|
|
`value` of the field, validation `label`, `error` function to generate an error
|
|
|
|
|
message, and an object containing all the `values` for the entire form.
|
2018-02-01 05:52:10 +03:00
|
|
|
|
|
|
|
|
|
Additionally, validation rules can pass an unlimited number of extra arguments.
|
|
|
|
|
These arguments are passed as the 2nd-nth arguments to the validation rule.
|
|
|
|
|
Their values are parsed from the optional parenthesis in the validation
|
|
|
|
|
attribute on the `formulate-element`.
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
<formulate-element
|
2018-02-01 18:47:11 +03:00
|
|
|
|
type="password"
|
|
|
|
|
name="password"
|
|
|
|
|
label="Password"
|
|
|
|
|
validation="confirmed(password_confirmation_field)"
|
2018-02-01 05:52:10 +03:00
|
|
|
|
/>
|
|
|
|
|
```
|
|
|
|
|
|
2018-11-20 19:51:32 +03:00
|
|
|
|
Validation rules should return an error message string if they failed, or
|
2018-02-01 05:52:10 +03:00
|
|
|
|
`false` if the input data is valid.
|
|
|
|
|
|
2018-03-14 01:58:24 +03:00
|
|
|
|
Adding your own validation rules is easy. Just pass an additional object
|
2018-02-01 05:52:10 +03:00
|
|
|
|
of rule functions in the plugin’s installation call:
|
2018-02-01 01:20:29 +03:00
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
Vue.use(formulate, {
|
|
|
|
|
rules: {
|
2018-02-01 18:47:11 +03:00
|
|
|
|
isPizza ({field, value, error, values, label}) {
|
|
|
|
|
return value === 'pizza' ? false : `label is not pizza.`
|
2018-02-01 05:52:10 +03:00
|
|
|
|
}
|
2018-02-01 01:20:29 +03:00
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
```
|
|
|
|
|
|
2018-02-01 05:52:10 +03:00
|
|
|
|
### Styling
|
|
|
|
|
|
|
|
|
|
Absolutely zero styles are included so feel free to write your own! The
|
|
|
|
|
`form-element` components have a wrapper `div` that receives the following
|
|
|
|
|
classes:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
formulate-element
|
|
|
|
|
formulate-element--has-value
|
|
|
|
|
formulate-element--has-errors
|
|
|
|
|
```
|
2018-02-01 01:20:29 +03:00
|
|
|
|
|
|
|
|
|
### Full Documentation
|
|
|
|
|
|
|
|
|
|
There are many more options available, more documentation coming soon.
|