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

vue-form-terminator

v0.2.3

Published

Vue form with validation

Downloads

6

Readme

vue-form-terminator

DEPENDANCIES

For proper functioning of vue-form-terminator please install dependencies

INTRODUCTION

This component contains a functional part of the form with the responsiveness, and styling is left as customizable.

It's created in a way to be easily integrated with third party CSS libraries like Bootstrap, SemanticUI, Font Awesome...

More about that in the styling section.

GIT SAMPLE

Follow the link for more information

Sample - https://github.com/RajovicMirko/vue-form-terminator-live

Git sample contains sample pages for:

  • NoStyle
  • Bootstrap
  • SemanticUI

INSTALLATION

npm i --save vue-form-terminator

IMPORT

In the primary vue project file main.js, index.js or whatever, use the following code

if vue-form-terminator.common is not imported, no initial style will be active. Is recommended to import it for the best experience

import VueFormTerminator from "vue-form-terminator";
import "vue-form-terminator/dist/vue-form-terminator.common";
Vue.use(VueFormTerminator);

Now the vue-form-terminator component is available in the whole vue app.

<template>
  <vue-form-terminator></vue-form-terminator>
<template>

USAGE

In the following sections, a simple registration page will be presented and the styling with bootstrap

For this demo let's use CDNs for bootstrap and font awesome.

In the main index.html in the head section add following code:

<!-- Bootstrap CDN -->
<link
  rel="stylesheet"
  href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
/>

<!-- FontAwesome CDN -->
<link
  href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css"
  rel="stylesheet"
/>

Then let's create a file named "Registration.vue" in "src/view" folder and paste the following code:

Code is explained after the script:

<template>
  <div id="registration">
    <vue-form-terminator
      v-bind="formSetup"
      :model="model"
      @submited="handleSubmit"
    >
    </vue-form-terminator>
  </div>
</template>

<script>
export default {
  name: "Registration",

  data() {
    return {
      model: {
        firstName: "John",
        lastName: "Doe",
        address: "Test street address",
        addressNumber: "123",
        username: "JohnDoe",
        email: "[email protected]",
        password: "12345",
        repeatPassword: "12345",
      },

      formSetup: {
        title: "Registration",
        positioning: {
          title: "",
          group: {
            title: "none",
          },
          input: {
            label: "",
            text: "",
            errorMessage: "",
          },
        },
        body: [
          {
            isGroup: true,
            title: "Personal data",
            otherClasses: "group-1",
            elements: [
              {
                id: "firstName",
                name: "FirstName",
                type: "text",
                label: "",
                placeholder: "First name",
                validations: {
                  required: {
                    message: "First name is required",
                  },
                  max: {
                    value: 30,
                    message: "First name must have less then 20 characters",
                  },
                },
                otherClasses: "form-control form-control-sm",
              },
              {
                id: "lastName",
                name: "LastName",
                type: "text",
                label: "",
                placeholder: "Last name",
                validations: {
                  required: {
                    message: "Last name is required",
                  },
                  max: {
                    value: 30,
                    message: "Last name must have less then 20 characters",
                  },
                },
                otherClasses: "form-control form-control-sm",
              },
              {
                id: "address",
                name: "Address",
                type: "text",
                label: "",
                placeholder: "Address",
                validations: {
                  required: {
                    message: "Address is required",
                  },
                },
                otherClasses: "form-control form-control-sm",
              },
              {
                id: "addressNumber",
                name: "HouseNumber",
                type: "number",
                label: "",
                placeholder: "No.",
                validations: {
                  required: {
                    message: "No. is required",
                  },
                  numberOnly: {
                    message: "Only numbers allowed",
                  },
                },
                otherClasses: "form-control form-control-sm",
              },
            ],
          },
          {
            id: "username",
            name: "Username",
            type: "text",
            label: "",
            placeholder: "Username",
            validations: {
              required: {
                message: "Username is required",
              },
              max: {
                value: 20,
                message: "Username must have less then 20 characters",
              },
              noWhiteSpace: {
                message: "No space character allowed",
              },
            },
            otherClasses: "form-control form-control-sm",
          },
          {
            id: "email",
            name: "Email",
            type: "text",
            label: "",
            placeholder: "Email",
            validations: {
              required: {
                message: "Email is required",
              },
              email: {
                message: "Email must be a valid email",
              },
            },
            otherClasses: "form-control form-control-sm",
          },
          {
            id: "password",
            name: "Password",
            type: "password",
            label: "",
            placeholder: "Password",
            validations: {
              required: {
                message: "Password is required",
              },
              min: {
                value: 5,
                message: "Pasword must have more then 5 characters",
              },
              max: {
                value: 20,
                message: "Pasword must have less then 20 characters",
              },
            },
            otherClasses: "form-control form-control-sm",
          },
          {
            id: "repeatPassword",
            name: "RepeatPassword",
            type: "password",
            label: "",
            placeholder: "Repeat Password",
            validations: {
              required: {
                message: "Repeat Pasword is required",
              },
              min: {
                value: 5,
                message: "Must have more then 5 characters",
              },
              max: {
                value: 20,
                message: "Repeat Pasword must have less then 20 characters",
              },
              compareElements: {
                value: "password",
                message: "Repeat Password must be equal as password",
              },
            },
            otherClasses: "form-control form-control-sm",
          },
        ],
        actions: [
          {
            id: "submit",
            name: "Submit",
            type: "submit",
            icon: "fas fa-check",
            otherClasses: "btn btn-outline-primary",
          },
          {
            id: "reset",
            name: "Reset",
            type: "reset",
            icon: "fas fa-times",
            otherClasses: "btn btn-outline-warning",
          },
        ],
      },
    };
  },

  methods: {
    handleSubmit(data) {
      console.log(data);
    },
  },
};
</script>
<style lang="scss">
$primary: #2185d0;

#registration {
  display: grid;
  grid-template-rows: auto 1fr;
  place-items: center;
  color: $primary;

  & .vue-form-terminator {
    width: 40%;
    min-width: 300px;

    & .titlenator {
      margin: 0;
    }

    & .group {
      &.outline {
        margin-bottom: 0.5rem;
      }

      &.group-1 {
        & .group-data {
          display: grid;
          grid-template-columns: 1fr 1fr 1fr 1fr;
          grid-gap: 0 1rem;

          & .inputnator {
            width: 100%;

            &.firstName {
              grid-column: 1/6;
            }
            &.lastName {
              grid-column: 1/6;
            }

            &.address {
              grid-column: 1/4;
            }

            &.addressNumber {
              grid-column: 4/6;
            }
          }
        }
      }
    }

    & .inputnator {
      padding-bottom: 0.3rem;

      & .errornator {
        font-size: 0.7rem;
        margin-top: 0.3rem;
      }
    }

    & .buttonator {
      margin-top: 1rem;
      & button {
        margin-bottom: 1rem;
      }
    }

    // BIG SCREEN
    @media (min-width: 768px) {
      & .group {
        &.group-1 {
          & .group-data {
            & .inputnator {
              &.firstName {
                grid-column: 1/3;
              }
              &.lastName {
                grid-column: 3/6;
              }
            }
          }
        }
      }

      & .buttonator {
        flex-direction: row;

        & button {
          width: 48%;
        }
      }
    }
  }
}
</style>

Registration page code explanation

So what's happening here

template

vue-form-terminator component props are:

  • two attributes:
    • model - not required
    • formSetup - required
  • submit handler:
    • method - required

All of the props and methods are explained in the script section.

script

formSetup

formSetup contains many attributes and I'll try to explain them all:

title - Form title

This is form title. If you don't enter a value, the title will not be presented.

positioning

This is an object that controls some of the elements positioning.

In the code below logic is:

attribute - type (valid values)

positioning: {
  title: string ("", "left", "center", "right"),
  group: {
    title: string ("", "none", "left", "center", "right"),
  },
  input: {
    label: string ( "", "none", "top", "bottom", "top left", "top center", "top right", "bottom left", "bottom center", "bottom right"),
    text: string ("", "left", "center", "right"),
    errorMessage: string ( "", "none", "top", "bottom", "top left", "top center", "top right", "bottom left", "bottom center", "bottom right")
  }
}
body - Form inputs

"body" object can include two types of schemas:

  • Single element object:

    • id - required (form model object keys depends on it)
    • name - not required
    • type - required (for now available values are text, number, password, email)
    • label - not required
    • placeholder - not required
    • validations - not required. Available validations are:
      • compareElements { value: 'id of body object to compare with' message: 'return this error message'}
      • email { message: 'return this error message' }
      • min { value: 'Number of min string length' message: 'return this error message'}
      • max { value: 'Number of max string length' message: 'return this error message'}
      • noWhiteSpace { message: 'return this error message'}
      • numberOnly { message: 'return this error message'}
      • required { message: 'return this error message'}
    • otherClasses - not required (use to integrate custom and thired party class names)
  • Group element object:

    • isGroup: required (set it to true)
    • title: not required
    • otherClasses - not required (use to integrate custom and thired party class names
    • elements - required (this is an array of "Single element object")

The main difference is that Single element is represented each in a new row, and Group element is represented in a single row.

Of course, the Group element can be controlled via CSS grid (as in the sample), and be reorganized in the way you need it.

actions - Form buttons

"actions" is an array of objects and it's attributes are:

  • id - required
  • name - required
  • type - required (for now available values are submit, reset)
  • otherClasses - not required (use to integrate thired party class names)

model

Form don't sync model, it creates a new one that is returned through the submit method as an object of all body elements.

Please try and see what is happening when you remove the model.

method

"data" parameter represents the new model.

handleSubmit(data) {
  console.log(data);
},

style

SCSS is used for styling and you can see that with a small amount of code we receive a very good result.

And Vue-la. That was it. :D :D :D :D

Third-party

For now are tested:

  • Bootstrap
  • SemanticUI
  • Font Awesome