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-base

v0.0.4

Published

Form-Generator: a Vue 2.0 component, reactive Result using Vuex, responsive Display

Downloads

24

Readme

Vue-Form-Base

Vue-Form-Base is a Vue 2.0 Component and Form-Generator for editing plain or deep nested Javascript objects getting a reactive Result.

You have to create a lot of different forms? Vue-Form-Base can simplify your job by creating forms from JS-Objects.

Select from different HTML5 Input-types like Text, Password, Checkboxes, Radios, Select, Multiselect, Color, Files or a lot of other fields. Apart from 'select' or multiselect' the Browser specific implementation of Input-Types is used. Some Informations to HTML5 input-types here

We use the Materialize CSS framework for styling. Input Fields have a clear, minimalistic design, but don't worry you can change your style with CSS in a lot of ways. For more details see section Style with CSS

Add global Validation to the form or validate only a single field. Use inline validation or write a new function for individuell validation.

Make complex data editable by mapping your incoming and outgoing data: i.e. change dateformats, trim strings or join/split arrays for editing in a textfield.

And finally get a full reactive Result by using Vuex.

Installation

npm install vue-form-base --save

Using single-file components with a .vue extension,

import Formbase.vue File from your path

import FormBase from 'vue-form-base';  

then register in

export default {	
	...
	components:{     
      FormBase
  	}
}

and use it in template

<template>
	<form-base :data="data" :schema="schema" data-state-name="datastate" />            
</template>

Minimalistic Example

If your data-state-name property has the value datastate, then you must additionally define datastate in Vuex State.

State:{ 
	datastate:null,
	... 
}

Now use existing Data Object

data:{ 
      name: 'smith',
      email:'[email protected]'
}

define the following minimalistic Schema

 schema:{ 
  name: {type:'text'},
  email: {type:'email'}
 
}

and get this full editable Form

Form Example

Edit using different Input-Types

A more realistic Example.

Your Data to edit:

data:{ 
  name: 'smith',
  email:'smith', 
  password: '12345ABCDEF',
  remember: 'undefined',
  adress:{ 
    city:'NY',
	 
  } 
},

Create a Schema Object:

schema:{ 
  
	user: {type:'text', label:'User:', placeholder:'User...',
		mapSet: (val, obj, data, schema) => { 
			// type 'hide' to hide dependent item password 
			schema.password.hidden = val === 'hide'; 
			return val;
		}
	},
 
	email: {type:'email',label:'Email:', validate:true }, 
	
	password: {type:'password', label:'Password(Numbers only):', pattern:'[0-9]*', validate: msg => console.log(msg) },
	
	remember: {type:'checkbox', label:'Remember Me:', true:'Yes', false:'No' }, 	
	
	adress:{ 
		city:{ type:'text', mapSet: v => v && v.toUpperCase() }
	} 
}

IMPORTANT:

Properties from Data-Object, which doesn't exist in Schema-Object, are ignored.

Reactive Result (Vuex)

Model Data und describing Schema flow as prop into the Vue-Form-Base. On the concept of one-way data flow you get reactive access to your modified data via Vuex Store $store.state.datastate . Installed Vuex is mandatory, details about Vuex you can find here Vuex-Introduction

<form-base :data="data" :schema="schema" data-state-name="datastate" />

If you need to dynamically modify the internal Schema (for example if you want to change dynamically schema.hidden to show/hide one item depending from the input of another item) you can have reactive access to the modified Schema via Vuex Store $store.state.schemastate.

Inside a single component .vue file you can use your component like this

<template>

   	<form-base 
	    :data="data" 
	    :schema="schema" 
	    data-state-name="datastate" 
	    schema-state-name="schemastate" 
	>
	</form-base>

</template>

Get Access to the reactive Result using Vuex State anywhere in your Project.

this.$store.state.datastate

IMPORTANT:

'Data' and 'Schema' passed as Prop becomes not mutated.

Two Forms can be reactiv Linked by using the same state property

<form-base :data="data" :schema="schema" data-state-name="dataCommon" />

<form-base :data="data" :schema="schema" data-state-name="dataCommon" />

and if you need different CSS

<form-base id="form1" :data="data" :schema="schema" data-state-name="dataCommon" />

<form-base id="form2" :data="data" :schema="schema" data-state-name="dataCommon" />

Reset modified Data and modified Schema use following code inside the parent single component .vue file

If you need to change the Schema-Object dynamically, like in this case hiding another item

schema:{
	...
	user: {
		type:'text', 
		mapSet: (val, obj, data, schema) => { schema.password.hidden = val === 'hide'; return val }
	},	
	password: {
	...
	}
}

then you need datastate and schemastate to restore like in this case

...
methods:{
    reset(){
      this.$store.state.datastate= cloneDeep(this.data); 
      this.$store.state.schemastate= cloneDeep(this.schema)
    },
    ...  
  },
  ...

In common use cases without modified Schema Reset can be shortened

<template>      
  <form-base :data="data" :schema="schema" data-state-name="datastate" />
</template>

<script>
	import { cloneDeep } from 'lodash'

	export default {
	...
	methods:{
	    reset(){
	      this.$store.state.datastate= cloneDeep(this.data); 
	    },
	    ...  
	},
	...
</script>

Schema

 <form-base :schema="schema" ... />

Schema is an object, which defines and controls the behavior of your form. Each Key in your schema-object must reflect a key in the data-object.

schema:{
	user: { type:'text'}, // minimalistic definition of input-type 
}


// more 

validate = val => console.log(val);
mapSet  = val => val + '!'
schema:{
	user: { 
		type:'text', 
		label:'User:', 
		pattern:'([A-Z]*)', 
		css:'blue', 
		validate, 			// is the same as - validate:validate,
		mapSet, 			// is the same as - mapSet:mapSet,
		order:1 
	},
	... 
}

In common use cases the the value will be another object with several properties, to get different control over the behaviour of your input-field.

Properties in Schema

schema:{ 
	order: number,          // controls order of displaying 
	
	type: string,           // 'text', 'password', 'email', ...
	label: string,          // title of item    
	placeholder: string,    // placeholder set null to hide 
	true: string,           // text if checkbox is checked  
	false: string,          // text if checkbox is unchecked 
	accept: string,         // type:'file' - limit files audio/*, image/*, .pdf
	title: string,          // define your own validation message
	error: string,          // preset/set inline error msg

	css: string,            // inject one or more classnames at item level 
	// Use 12 column grid system from materializecss.com/grid.html for displaying items
	// for example a 12 column grid with 3 items in one row would look like:
	// schema:{ item1:{ css:'col s4'}, item2:{ css:'col s4'}, item3:{ css:'next-row col s4'} }
 	
	pattern: string,        // regex to control input  
	
	min: number,            // limit number or range
	max: number,            // limit number or range
	step: number,        
	maxlength: number,      // max length of type text, password, email 
	
	multiple: bool,         // type:'file' select one or more files   
	required: bool,         // need an input value
	disabled: bool,         // disable input field
	readonly: bool,          
	hidden: bool,           // hide item - set from another item
	
	options: array,         // used with type: radio, list, text, select, mselect

	mapGet: function,       function( val, obj, state, schema ) {... return val}	
	mapSet: function,       function( val, obj, state, schema ) {... return val} }
	
	validate: true          // use inline error message
	validate: function,     function( msg, obj, state, schema, validity ) {...}         
	noValidate: function,   function( value, obj, state, schema ) {...}
}          
      

Real-Life Example

...
schema:{ 
    
    user: { type:'text', label:'Fullname:', placeholder:'Name...', css:'col s6'}, 
    
    email: {type:'email', validate:true, mapSet: v => v && v.toUpperCase(), css:'next-row col s6' },
    
    singleRole:{ type:'select', options:['Admin','Guest','User'] }, 
   
  }
  ...

Style with CSS

Customize your vue-form-base component using the following CSS-Classnames

IMPORTANT:
Don't use <style scoped> in parents component, because scoped definitions are inside the child component not accessable

Form-ID

#form-base is the default form-id. If you need different CSS for two or more forms in the same parent component, then change default value by setting a different id for each component and use this new id

/* default */
<form-base ... />  
#form-base .collection {...}

/* individualize it */
<form-base id="my-custom-id" ... />  
#my-custom-id .collection {...} 

General - Classnames

  #form-base .collection {...}   	// style container for all items	   
  #form-base .item {...}     		// each key is represented, by an item   
  #form-base .error {...}        	// style inline-error messages 	  
  

Validate with Pseudoselectors

  #form-base .item input:invalid { background-color: #fdd; }
  #form-base .item input:valid { background-color: #dfd; }
  #form-base .item input:focus { background-color: #ffd; }          

Type - Classnames

Style all items of a specific type, then use type-classnames. They start with a type ie. password appending -type. Then you have a classname password-type

#form-base .text-type {...}  or  #form-base .item.text-type {...}

You can use most of HTML5 input-types like <input type="password" />. Some Informations to HTML5 input-types

/*	
	Available Types:
	text,  password, email, select, multiselect, list, file, radio, 
	checkbox, number, range, url, date, time, week, month 
	
	use class by appending -type  ->  .text-type 
*/

  #form-base .text-type { font-weight:500 }
  #form-base .item.select-type {...}
  #form-base .item.multiselect-type {...}
  #form-base .item.checkbox-type {...}
  

Make validate CSS for multiselect type

If you want to style select or multiselect types you have append select after the classname

 #form-base .item.multiselect-item select { height:6rem }

Key - Classnames

Here you get direct access to each key in your Data-Object. If you want access deep nested keys youst must use a hyphen

data{ user:{ adress:{ city:'',... } ... } ... }

access deep nested key 'city' with CSS

  #form-base .item.user-adress-city-key {...}    

Example

a) Use Example with vue-webapp template, checkout example directory in this repo and follow the readme.

b) Here is a working Vue-File, you can integrate this in your vue-project. Lodash and Vuex must be installed. In initial Vuex state definition state.datastate must exist

<style>
  #form-base .error { color:red}
  #form-base .item input:invalid{ background-color: #fdd; }
</style>

<template>
  {{$store.state.datastate}}
  <form-base :data="data" :schema="schema" data-state-name="datastate" />             
</template>

import FormBase from './FormBase.vue';  

export default {

  data () {
    return {  
  
      data:{
        user: 'smith',
        pw: 'secret'			
      },       
          
      schema:{
        user: { 
      		type:'text', 
          	label:'User:',
			placeholder:'User...'    
        },
        pw: { 
			type:'password',
			pattern:'^.{6,}', 
			lable:'Password:',
			title: 'Password must have minimal 6 Chars',
			required:true,
			validate:true
        }
      }  
    } 
  },

  components:{     
      FormBase
  }
}  
  

Features

  • vue-component
  • edit plain or deep nested objects
  • support most of input types
  • full reactive result
  • configurable via Schema Defintion
  • configurable Style based on Materialize CSS

Dependencies

  • Vue 2.0

  • Vuex

  • Lodash

  • Materialize CSSs

Similar Projects

vue-form-generator

vue-formular