panda-form
v0.1.2
Published
A react modx form component library
Downloads
2
Readme
Panda Forms
Panda Forms is a form library made with react and mobx to provide a way to rapidly develop forms with basic front end validation. Panda Forms comes pre-built with validation for expiration dates on credit cards, credit cards, dates, email addresses, and required fields. There is built in styles for all of the form elements but you are not required to use them for Panda Forms to function.
Simple Example
// App.js
import {observer} from 'mobx-react';
import {Form, FormRow, TextInputGroup, GroupContainer, RadioButtonGroup} from 'panda-form';
@observer
export default class App extends React.Component {
constructor(props){
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(type, event){
this.props.formStore.updateInfo(type, event.target.value);
}
handleSubmit(){
let canSubmit = this.props.formStore.validateAll();
if(canSubmit){
// code to submit form
}
}
render(){
let values = this.props.formStore.info;
return(
<Form title='Example' styleClass='panda-form'>
<FormRow styleClass='form-row'>
<TextInputGroupgroup
Width='49%'inputWidth='100%'
label='Email Input'
required={true}
changeFunction={this.handleChange}id={'$email-email'}
value={values.$emailEmail}
placeholder='Enter Text'
inputStyleClass='text-group__text-input'
labelStyleClass='text-group__label'/>
<GroupContainergroup
Width='49%'
label='Check Box Group'
labelStyleClass='group-container__label'
required={false}
>
<CheckboxGroup
inputStyleClass='checkbox-group__checkbox'
labelStyleClass='checkbox-group__label'
groupStyleClass='checkbox-group'
checked={values.$checkboxCheckboxA}
id='$checkbox-checkbox-a'
required={true}
groupWidth='100%'
label='Check this box A'
changeFunction={this.handleChange}
/>
<CheckboxGroup
inputStyleClass='checkbox-group__checkbox'
labelStyleClass='checkbox-group__label'
groupStyleClass='checkbox-group'
checked={values.$checkboxCheckboxB}
id='$checkbox-checkbox-b'
required={false}
groupWidth='100%'
label='Check this box B'
changeFunction={this.handleChange}
/>
<CheckboxGroup
inputStyleClass='checkbox-group__checkbox'
labelStyleClass='checkbox-group__label'
groupStyleClass='checkbox-group'
checked={values.$checkboxCheckboxC}
id='$checkbox-checkbox-c'
required={false}
groupWidth='100%'
label='Check this box C'
changeFunction={this.handleChange}
/>
</GroupContainer>
</FormRow>
</Form>
)
}
}
// Main.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
import 'babel-polyfill';
import {FormStore} from './stores/FormStore';
const initialInfo = {
$emailEmail: '',
$checkboxCheckboxA: '',
$checkboxCheckboxB: '',
$checkboxCheckboxC: ''
}
const required = ['$email-email', '$checkbox-checkbox-a'];
const dateFormat = 'MM/DD/YYYY';
let formStore = new FormStore(initialInfo, required, dateFormat);
ReactDOM.render(
<App formStore={formStore} />,
document.getElementById('app')
);
Documentation
styles
components
- CheckboxGroup
- DateInputGroup
- ExpirationInputGroup
- ErrorGroup
- Form
- FormRow
- FormButton
- GroupContainer
- RadioButtonGroup
- SelectGroup
- TextBoxGroup
- TextInputGroup
store
utils
- camelToSnake
- isNumber
- isValidCreditCard
- isValidDate
- isValidEmail
- isValidString
- radioStringFormat
- regex
- removeTokens
- snakeToCamel
- snakeToError
Styles
To use the default styles include the panda-form.css stylesheet found in lib/assets and follow the naming conventions outlined below.
Components
Have the changeFunction on components call this.props.formStore.updateInfo to properly validate
- CheckboxGroup
- DateInputGroup
- ExpirationInputGroup
- ErrorGroup
- Form
- FormRow
- FormButton
- GroupContainer
- RadioButtonGroup
- SelectGroup
- TextBoxGroup
- TextInputGroup
CheckboxGroup
creates a checkbox with a label to the right
group multiple checkboxes inside of a group container
must have $checkbox token in front of checked prop and id prop to function correctly
PropTypes
- groupWidth : string
- label : string
- labelStyleClass : string
- changeFunction : function required
- checked : boolean required
- groupStyleClass : string required
- id : string required
- inputStyleClass : string required
- required : boolean required
Config (for default style and validation)
inputStyleClass='checkbox-group__checkbox'
labelStyleClass='checkbox-group__label'
groupStyleClass='checkbox-group'
checked={this.props.formStore.info.$checkboxWhateverYouWant
id='$checkbox-whatever-you-want'
ErrorGroup
creates a box to display errors
use formStore.errors if not managing yourself
include stylesheet for default styles
PropTypes
- errors array required
Config (for default behavior)
errors={this.props.formStore.errors}
ExpirationInputGroup
displays credit card expiration inputs
currently only supports 2 digit lengths for month and year
must have $expiration token in front of value and id prop to function correctly
PropTypes
- groupStyleClass : string
- groupWidth : string
- label : string
- labelStyleClass : string
- monthMaxLength : number
- monthPlaceholder : string
- monthStyleClass : string
- monthWidth : string
- yearMaxLength : number
- yearPlaceholder : string
- yearStyleClass : string
- yearWidth : string
- changeFunction : function required
- idMonth : string required
- idYear : string required
- required : boolean required
- valueMonth : string required
- valueYear : string required
Config (for default style and validation)
monthStyleClass='expiration-group__text-input'
yearStyleClass='expiration-group__text-input'
valueMonth={values.$expirationWhatever}
valueYear={values.$expirationWhatever}
idMonth='$expiration-whatever'
idYear='$expiration-whatever'
monthMaxLength={2}
yearMaxLength={2}
Form
acts as a container for other components. not required for other components to work
PropTypes
- title : string
- styleClass : string
- styles : object
Config (for default style)
styleClass='panda-form'
Example
<Form styleClass='panda-form'>
<child-component />
<child-component />
<child-component />
</FormRow>
FormButton
calls the submit function. submit function should call formStore.validateAll.
include stylesheet for default style
symbol is what follows after text
PropTypes
- styleClass : string
- symbol : string
- submitFunction : function required
- text : string required
Config (for default style)
FormRow
wraps other components into a row
doesn't do anything if stylesheet not used
PropTypes
- styleClass : string
Config (for default style)
styleClass='form-row'
Example
<FormRow styleClass='form-row'>
<child-component />
<child-component />
<child-component />
</FormRow>
GroupContainer
used to wrap groups of elements (mostly checkboxs or radio buttons)
required set to true will put an asterisk next to the label
PropTypes
- groupStyleClass : string
- groupWidth : string
- label : string
- labelStyleClass : string
- required : boolean required
Config (for default style)
labelStyleClass='group-container__label'
Example
<GroupContainer
groupWidth='49%'
label='Group'
labelStyleClass='group-container__label'
required={true}
>
<child-component />
<child-component />
<child-component />
</GroupContainer>
RadioButtonGroup
creates a radio button with a label to the right
group multiple radio buttons inside of a group container
must have $radiobtn$radiogrpGroupname token in front of checked prop and id prop to function correctly
can only be used in groups for select one (ie no multiselct within a group)
you can have multiple radio button groups they just need a different group name
PropTypes
- groupWidth : string
- label : string
- labelStyleClass : string
- changeFunction : function required
- checked : boolean required
- groupStyleClass : string required
- id : string required
- inputStyleClass : string required
- required : boolean required
Config (for default style and validation)
inputStyleClass='radio-button-group__button'
labelStyleClass='radio-button-group__label'
groupStyleClass='radio-button-group'
checked={values.$radiobtn$radiogrpGroupnameWhatever}
id='$radiobtn-$radiogrp-cats-groupname-whatever'
SelectGroup
creates a select box
PropTypes
- groupStyleClass : string
- groupWidth : string
- inputStyleClass : string
- inputWidth : string
- label : string
- labelStyleClass : string
- maxLength : number
- placeholder : string
- changeFunction : function required
- id : string required
- options : array *required
- required : boolean required
- value : string required
Config (for default style and validation)
inputStyleClass='select-group__select'
labelStyleClass='text-group__label'
value={this.props.formStore.info.whatever}
TextBoxGroup
creates a text area input
PropTypes
- groupStyleClass : string
- groupWidth : string
- inputStyleClass : string
- inputWidth : string
- label : string
- labelStyleClass : string
- maxLength : number
- placeholder : string
- rows : number
- changeFunction : function required
- id : string required
- required : boolean required
- value : string required
Config (for default style and validation)
inputStyleClass='text-box__input'
labelStyleClass='text-group__label'
value={this.props.formStore.info.whatever}
TextInputGroup
creates a text input
must have $credit token or $email token (if being used for those) in front of value and id prop to function correctly
PropTypes
- groupStyleClass : string
- groupWidth : string
- inputStyleClass : string
- inputWidth : string
- label : string
- labelStyleClass : string
- maxLength : number
- placeholder : string
- changeFunction : function required
- id : string required
- required : boolean required
- value : string required
Config (for default style and validation)
inputStyleClass='text-group__text-input'
labelStyleClass='text-group__label'
value={this.props.formStore.info.whatever}
// if validating as email
value={this.props.formatStore.info.$emailWhatever}
id={$emailWhatever}
// if validating as credit card
value={this.props.formatStore.info.$creditWhatever}
id={$creditWhatever}
__
store
The store is used to handle validation and to manage the state of the form.
formStore
The formStore is a class wrapped in a mobx observable. You should import the store and initiate it at the top of your app. You should have one store for a form but you can have multiple stores and multiple forms if you want.
import FormStore from 'panda-form';
let formStore = new FormStore(/* info object */, /* required array */, /* date format string */);
The info object is a key value pair for all of the form items you want to keep track of and what you want their initial value to be. The keys should be camel case, and any validation tokens you use should be first. The id's that give to the form elements are snake case version of the key names. If you need to convert there are functions that you can import from utils called camelToSnake and snakeToCamel that return a converted string value.
//example
let info = {
firstName: '',
$creditCreditCard: '',
$checkboxRed: false,
$radiobtn$radiobtngrpCatBlack: false,
$radiobtn$radiogrpCatOrange: false
}
The required array is an array of strings which are the camel case of the key name in the info object and determine what fields will be validated for required. For a radio button group you just put in $radiogrp-groupname.
//example
let required = [
'first-name',
'$credit-credit-card',
'$radiogrp-cat'
]
The date format string is just a string. Currently it can only be 'MM/DD/YYY'
or 'YYYY/MM/DD'
. It is
only needed if you are going to use the DateInputGroup component.
validation
There are several tokens that you can put on your info keys and ids that tell the store how to validate information. In order to validate it as required make sure the proper value in the required array passed into the new formStore object.
$credit
validates the value in the info object as a credit card
- camelCase: $creditWhatever
- snake-case: $credit-whatever
$checkbox
lets the store know how to update a checkbox field. Currently can only require one checkbox and not groups of checkboxes.
- camelCase: $checkboxWhatever
- snake-case: $checkbox-whatever
$date
validates the value in the info object as a date. date format must be 'MM/DD/YYYY'
or 'YYYY/MM/DD'
- camelCase: $dateWhatever
- snake-case: $date-whatever
$expiration
validates that the value is numerical and 2 digits in length
- camelCase: $expirationWhatever
- snake-case: $expirationWhatever
validates the value in the info object as an email address
- camelCase: $emailWhatever
- snake-case: $email-whatever
$radiobtn$radiogrp
validations a group of radio buttons (currently can't have a single radio button). you must put the group name after $radiogrp.
- camelCase: $radiobtn$radiogrpGroupnameWhatever
- snakeCase: $radiobtn-$radiogrp-groupname-whatever
utils
The utils are the various utilities utilized by the formStore but they can be useful on their own if not using the store.
// example
import utils from 'panda-form'
utils.camelToSnake('camelCase');
- camelToSnake
- isNumber
- isValidCreditCard
- isValidDate
- isValidEmail
- isValidString
- radioStringFormat
- regex
- removeTokens
- snakeToCamel
- snakeToError
camelToSnake(type: string): string
Takes a string in form camelCase and returns it as snake-case
let type = 'isWhatever'
let newType = utils.camelToSnake(type)
// newType = 'is-whatever'
isNumber(value: string): boolean
Takes a string and determines if it is a number.
let value = '123';
let isValid = utils.isNumber(value);
// isValid = true;
isValidCreditCard(value: string): boolean
Takes a string and determines if it is a valid credit card number.
let value = '4444 4444 4444 4444';
let isValid = utils.isValidCreditCard(value);
// isValid = true;
isValidDate(value: string): boolean
Takes a string and determines if it is a date of format 'MM/DD/YYYY'
or 'YYYY/MM/DD'
.
let value = '12/13/1987';
let isValid = utils.isValidDate(value);
// isValid = true;
isValidEmail(value: string): boolean
Takes a string and determines if it is a valid email.
let value = '[email protected]';
let isValid = utils.isValidEmail(value);
// isValid = true;
isValidString(value: string): boolean
Takes a string and determines if it's length is greater then 0.
let value = '';
let isValid = utils.isValidString(value);
// isValid = false;
radioStringFormat(type: string): string
Takes a camel case string and seperates $radiobtn$radiogrp into $radiobtn-$radiogrp.
let type = '$radiobtn$radiogrp-cats-black'
let newType = utils.radioStringFormat(type);
// newType = '$radiobtn-$radiogrp-cats-black'
regex
contains the regex for getting all of the various tokens.
- regex.date -> $date
- regex.checkbox -> $checkbox
- regex.radio -> $radiobtn
- regex.radioGroup -> $radiogrp
- regex.expiration -> $expiration
- regex.email -> $email
- regex.credit -> $credit
let rx = utils.regex.email;
let value = '$email-whatever';
let isEmail = rx.test(value);
//isEmail = true
removeTokens(type: string): string
Takes a snake-case string and removes the tokens from it and returns a snake case string
let type = '$credit-whatever';
let newType = utils.removeTokens(type);
// newType = 'whatever'
snakeToCamel(type: string): string
Takes a string in form snake-case and returns it as camelCase
let type = 'is-whatever'
let newType = utils.snakeToCamel(type)
// newType = 'isWhatever'
snakeToError(type: string): string
Takes a string in the form snake-case and returns it without tokens in the form 'Capital Case With Spaces'
let type = $credit-credit-card;
let newType = utils.snakeToError;
// newType = 'Credit Card'