npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@andresouzaabreu/vue-form-builder

v3.0.0

Published

A Vue plugin that automatically generates beautiful forms.

Downloads

15

Readme

VUE FORM BUILDER

A Vue plugin that automatically generates beautiful forms using bootstrap and displays error messages from the server.

Table of contents

  1. Demo
  2. Features
  3. Getting started
  4. Configuration
  5. License
  6. Versioning
  7. Contributing
  8. Authors

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}$"
    /*... more aliases*/
};

// add single alias
fieldAliases.setAlias("birthday", "name:birthday|date|label:Your birthday");

// add new aliases in addition to the default ones
fieldAliases.setAliases(customAliases);

// you may want to remove an alias
fieldAliases.removeAlias("email");

// or maybe reset all aliases
fieldAliases.resetAliases();

// get the aliases (we probably won't need this, unless to debug)
console.log(fieldAliases.getAlias("country"));

// get all of them
console.log(fieldAliases.getAliases());

Note: Define your custom aliases before registering FormBuilder as Vue component.

slots

Vue Form Builder has three slots that allow us to customize our forms.

  • Start: appends content before creating the fields we specify.
  • Default: inserts content after creating the fields we specify.
  • End: prepends content after the form buttons.

Example:

<template>
    <div>
        <form-builder v-bind="{ fields, model, errors }">
            <template #start>
                <p>We need to collect some personal information before we proceed</p>
            </template>
            <div>
                <select id="custom-select"></select> <!-- a custom select -->
            </div>
            <template #end>
                <p>By submitting this form, you agree with our terms and conditions</p>
            </template>
        </form-builder>
    </div>
</template>
<script>
export default {
    data() {
        return {
            fields: [
                "name:name|text",
                "name:email|email|label:Email address",
            ],
            model: {
                /* ... */
            },
            errors: {
                name: ["Name too long", "Only characters allowed"]
            },
        };
    }
};
</script>

Will render something like

<!-- Any HTML comments that are listed below won't show up.
They are just explaining things -->
<div>
    <form>
        <!-- start -->
        <p>We need to collect some personal information before we proceed</p>
        <!--/start -->

        <div class="form-group">
            <label for="name">Name</label>
            <!-- class is invalid is due to errors -->
            <input class="form-control is-invalid" name="name" id="name" type="text">

            <!-- below are the errors. They show up only if specified -->
            <div class="help-block invalid-feedback">
                <span>Name too long</span>
                <span>Only characters allowed</span>
            </div>
        </div>
        <div class="form-group">
            <label for="email">Email address</label>
            <input class="form-control" name="email" id="email" type="email">
        </div>

        <!-- default -->
        <div>
            <select id="custom-select"></select>
        </div>
        <!--/default -->

        <div class="form-group form-button-container">
            <button class="btn btn-danger" type="reset">CANCEL</button>
            <button class="btn btn-success" type="submit">SAVE</button>
        </div>

        <!-- end -->
        <p>By submitting this form, you agree with our terms and conditions</p>
        <!--/end -->
    </form>
</div>

errors outside the form

We can display the errors outside VueFormBuilder.

Example below will not display error inside the form, but will show them as a list of error above the form. That is useful to display error somewhere else in the webpage.

<template>
    <div>
        <div class="custom-error-list">
            <!-- the errors prop must be A FLAT ARRAY OF STRINGS !
            The errors will be displayed as a list -->
            <error-list :errors="errors" errorMessage="Ops! Please, correct your input as indicated" />
        </div>
        <form-builder v-bind="{ fields, model, showInlineErrors: false }" />
    </div>
</template>
<script>
import { ErrorList } from "@andresouzaabreu/vue-form-builder";
export default {
    components: { ErrorList },
    data() {
        return {
            model: /**/,
            fields: /**/,
            errors: /**/,
        }
    },
}
</script>

We can also use inline error if we have more complex fields (which VueFormBuilder may not be able to render)

<template>
    <form-builder v-bind="{ fields, model }" >
        <div class="form-group">
            <label>Article body</label>
            <textarea id="ckeditor" name="body">
            <inline-error v-if="errors.body" :errors="errors.body">
        </div>
    </form-builder>
</template>
<script>
import { InlineError } from "@andresouzaabreu/vue-form-builder";
export default {
    components: { InlineError },
    /* ... */
}
</script>

License

See the LICENSE file for details

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Author

  • André Souza Abreu - Initial work - Github

See also the list of contributors who participated in this project.