README
VUE FORM BUILDER
A Vue plugin that automatically generates beautiful forms using bootstrap and displays error messages from the server.
Table of contents
Demo
The best way to see if a package suits your needs is by viewing and editing a demo project. Here are some code playground in which you can test Vue Form Builder.
Features
- Automatically displays inline error messages from a Laravel server
- Automatically generates form fields with bootstrap classes
- Can create any form field (select, checkbox, range, date, textarea, password, etc)
- Is highly customizable (pass any html attribute to a field; allows labels to render html)
- Custom aliases
- Smart guessing
Smart guessing
Vue Form Builder allows us to omit certain parameters. It will guess what we want based on what we provide. For example, if we pass ["name", "email", "password", "password_confirmation"], Vue Form Builder will create four input fields with the name, id, label, and type matching the given items.
If we don't specify a css id, a label text, Vue Form Builder will use the name attribute as a fallback for these values. Moreover, it converts name attributes (created_at, personalInfo, etc) to a more human-friendly format (Created at, Personal Info).
Another example is that, if you specify the type attribute, you don't need to specify the field's tag name (input, textarea, select) because only input elements have a type attribute. Vue Form Builder will automatically creates an input element if you specify the type attribute.
Getting started
Installation
npm install --save @andresouzaabreu/vue-form-builder
Set up
// globally
import FormBuilder from '@andresouzaabreu/vue-form-builder';
Vue.component("form-builder", FormBuilder)
//locally
import FormBuilder from '@andresouzaabreu/vue-form-builder';
export default {
name: "MyComponent"
components: {
FormBuilder,
}
}
Besides bootstrap, Vue Form Builder uses its own css. Add these lines below to main.js to import the stylesheets.
import 'bootstrap/dist/css/bootstrap.min.css'
import '@andresouzaabreu/vue-form-builder/dist/FormBuilder.css'
Use
<template>
<div>
<form-builder v-bind="{ fields, model, errors }"/>
</div>
</template>
<script>
export default {
data() {
return {
fields: [
"name:name|text",
"name:email|email|label:Email address",
"file|name:photo",,
{
name: "role",
type: "checkbox",
options: ["Admin", "Editor", "Author", "User", "Manager"]
}
],
model: {
name: "",
email: "",
photo: "",
role: "",
},
/* each key in the error object should be the name of a form field.
Its value should be an array of strings (each string is an error)
*/
errors: {}
}
}
}
</script>
Configuration
| prop | type | default | description |
|---|---|---|---|
| fields | Array |
- | Specify how the form fields should be rendered |
| model | Object |
- | When user inputs something, it will update the model object. |
| errors | Object |
{} |
Error messages to display |
| formButtons | Object |
{} |
Specify how to display the form buttons |
| fieldClass | String |
form-control |
The css class of form fields |
| fieldGroupClass | String |
form-group |
The css class of the div wrapping the form fields |
| showButtons | Boolean |
true |
Whether to render the form buttons provided by Form Builder |
| showInlineErrors | Boolean |
true |
Whether to display the error message inline |
| showErrorList | Boolean |
false |
Whether to display the error messages as a list |
fields
The fields array contains objects or strings representing a field. Here are some examples:
[
// we can pass any id, class, etc
'name:personal_info|textarea|class:pretty-editor',
'name:article|textarea|id:ckeditor',
// we can pass any html attributes
'name:age|min:18|max:60|required|label:Enter your age, please|number',
'name:phone|pattern:^[0-9]{2}-[0-9]{4}-[0-9]{4}$|label:Phone number|text',
'name:id|hidden|element:input',
"name:birthday|date",
// we can use html in our labels
'name:ccd|number|label: Credit Card code ' +
'<i class="fa fa-info" data-toggle="tooltip" title="The three digits behind the card"></i>',
// we can pass objects
"name:gender|range|options:" + JSON.stringify({M: "male", F: "female"}),
{
name: "country",
options: {...["China", "Spain", "USA", "Canada"]}
},
]
If the field is a string, we need to use | to separate the field attributes (this can be Html attributes, label text, element type, select options, etc). The order of the attributes does not matter (e.g, name:email|text is the sane as text|name:email).
model
The model object contains the values of the form fields. The field value the user inputs will get updated in the model.
Javascript Example:
export default {
name: "LoginForm",
data() {
return {
fields: [
'name:username|label:Your username please|text',
'name:password|label:Your password please|password',
],
model: {
username: "",
password: "",
},
errors: {}
}
},
methods: {
attemptLogin() {
axios.post('/api/login', this.model).then(response => {
/* log the user in */
}).catch(error => {
/* the response from the server can be accessed through error.response
The response object contains things such as headers, status code, and so
on. We are interested in the data property of the response object. The
data property should have the validation errors.
*/
let data = error.response.data;
this.errors =data.errors;
})
}
}
}
in vue template:
<form-builder v-bind="{ fields, model, errors }" @submit="attemptLogin()">
errors
The errors prop must be an object with keys equal to the field names and values equal to an array of error for the associated field. For Example:
{
username: ["Username must be at least 5 characters long", "Username can contain only letters and numbers"],
email: ["Invalid email"],
password: ["Password confirmation does not match"]
}
formButtons
| prop | type | default |
|---|---|---|
| submitButtonText | String |
"SAVE" |
| cancelButtonText | String |
"CANCEL" |
| submitButtonAttr | Object |
{class: "btn btn-success", type: "submit"} |
| cancelButtonAttr | Object |
{class: "btn btn-danger", type: "reset"} |
| wrapperAttr | Object |
{class: "form-group form-button-container"} |
Note: Attr means Html Attributes in this context.
showButtons
Vue Form Builds automatically appends form buttons at the bottom of the form. You can disable that by setting showButtons to false. You can use your own form buttons. For example:
<template>
<form-builder v-bind="{ fields, model }">
<div>
<button @click="submit()">SAVE</button>
<button @click="resetForm()">CANCEL</button>
</div>
</form-builder>
</template>
aliases
You can use aliases to reuse the same configuration accross multiple forms. Here is one example.
fields: ["name", "email", "age", "photo", "password", "password_confirmation"]
This will generate the following HTML:
<form>
<div class="form-group">
<label for="name">Name</label>
<input id="name" name="name" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="email">Email</label>
<input id="email" name="email" type="email" class="form-control" />
</div>
<div class="form-group">
<label for="age">Age</label>
<input id="age" name="age" type="number" class="form-control"/>
</div>
<div class="form-group">
<label for="photo">Photo</label>
<input id="photo" name="photo" type="file" accept="image/*" class="form-control"/>
</div>
<div class="form-group">
<label for="password">Password</label>
<input id="password" name="password" type="password" class="form-control"/>
</div>
<div class="form-group">
<label for="password_confirmation">Password confirmation</label>
<input id="password_confirmation" name="password_confirmation" type="password" class="form-control"/>
</div>
<div class="form-group form-button-container">
<button type="reset" class="btn btn-danger">CANCEL</button>
<button type="submit" class="btn btn-success">SAVE</button>
</div>
</form>
The following aliases are enable by default:
{
name: "name:name|text",
fname: "name:fname|text",
lname: "name:lname|text",
username: "name:username|text",
email: "name:email|email",
email_confirmation: "name:email_confirmation|email",
password: "name:password|password",
password_confirmation: "name:password_confirmation|password",
age: "name:age|number",
birthday: "name:birthday|date",
photo: "name:photo|file|accept:image/*",
picture: "name:picture|file|accept:image/*",
profile_picture: "name:profile_picture|file|accept:image/*",
}
We can override the aliases above or define our custom aliases as follow:
import { fieldAliases } fro '@andresouzaabreu/vue-form-builder';
const customAliases = {
country: "name:country|text",
phone: "name:phone|number|label:Phone number|pattern:^[0-9]{4}-[0-9]{4}