@adrenalin/react-form
v2.0.3
Published
Adrenalin Media - React Form Validation Component
Downloads
113
Readme
Adrenalin Media - React Form
A React form validation wrapper and templating component. It supports all base html field types (input, textarea, select, radio, checkbox) and includes a few base validation rules for standard validations such as email, password, digits etc.
It includes support for adding custom validators via a defined validator object structure as well as the ability to overide the default field template component at either the parent ReactForm
or child ReactFormField
level.
Useage
This component uses NPM to install and manage versioning.
Installation
As this is a private npm package, authentication is first required.
npm login
# Username: adrenalin
# Password: *********
# Email: [email protected]
Then install the module -
yarn add @adrenalin/react-form
or
npm install @adrenalin/react-form
Getting Started
The module exposes 2 main components, the parent ReactForm
and the child ReactFormField
fields.
ReactForm
represents the form wrapper and will return a <form>
element around its children.
ReactFormField
is then used to identify the form inputs to be captured by the form. These can be placed at any child level allowing for custom form layouts. The field comes with a predefined component template layout that will handle the input states, label and errors. The module also includes SCSS for the default field component template.
ReactFormField
fields can also be dynamically added or removed from the form which will update it's validation state on each props.children
change.
Below is a basic example of use inside a react Component -
Javascript
import React, { Component } from "react";
import { ReactForm, ReactFormField } from "@adrenalin/react-form";
class FormApp extends Component {
handleFormValidated(formData) {
console.log("Success:", formData);
}
handleFormError(formData) {
console.log("Error:", formData);
}
render() {
return (
<ReactForm
onSuccess={this.handleFormValidated.bind(this)}
onError={this.handleFormError.bind(this)}
>
<ReactFormField
type="text"
name="firstName"
id="firstname"
label="First Name"
placeholder="First Name"
required={true}
validators={["name"]}
errorMessages={{
required: "Please enter your first name."
}}
/>
<ReactFormField
type="select"
name="selector"
label="Select a value"
required={true}
errorMessages={{
required: "Please select an option."
}}
>
<option value="">Select an option</option>
<option value="first">First option</option>
<option value="second">Second option</option>
<option value="third">Third option</option>
</ReactFormField>
<ReactFormField
type="checkbox"
name="terms"
label="Please agree to the terms."
required={true}
errorMessages={{
required: "Please make sure you agree to the terms."
}}
/>
<button type="submit">Submit</button>
</ReactForm>
);
}
}
SCSS
The module comes with SCSS to handle the structual styles of the returned ReactFormField
template component.
This can be imported as per below -
// Import base scss from @adrenalin/react-form npm module
@import "~@adrenalin/react-form/scss/index";
SCSS Variables
To assist with modifying the default template styles there are number of SCSS variables that can be predefiend before importing the module scss.
// ReactForm override variables
$reactform_color_success: lighten(blue, 20%); // success state color
$reactform_color_error: lighten(red, 20%); // error state color
$reactform_field_padding: 1em; // left/right padding for input, select, textarea elements
$reactform_field_bg: #efefef; // background color for field inputs
$reactform_field_margin: 20px; // top/bottom margin between each field
$reactform_input_size: 1.25em; // height of the text input and select elements/labels
$reactform_textarea_size: 10em; // height of the textarea element/label
$reactform_radio_size: 2em; // height of the radio element/label
$reactform_checkbox_size: 2em; // height of the checkbox element/label
// Import base scss from @adrenalin/react-form npm module
@import "~@adrenalin/react-form/scss/index";
Props
ReactForm
Most props provided to ReactForm
will automatically be passed down to the <form>
element. Below are the custom ReactForm
specific props.
| Prop | Type | Description |
| ------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| onSuccess
| function | A callback function which returns an array of all the form fields as objects with their name and value. Fired on the form submit action when all required fields and validations are met. |
| onError
| function | A callback function which returns an array of all the form fields as objects with their name and value. Fired on the form submit action when any required fields or validations fail to validate. |
| disableErrorScroll
| boolean | If true the form will not attempt to scroll to the first invalid input in the form on form submit. |
| disableSubmitUntilValid
| boolean | If true any child type="submit"
buttons will have a disabled prop and class added to them until the form reaches a valid state. |
| validators
| array | An array of validator patterns to extend the default validators. Custom validators are detailed further here. |
| fieldComponent
| component | A react template component that will override the default Field component. More info on custom field template components here. |
| pageSubmit
| boolean | If true, preventDefault will only be called if the form is invalid. Useful if you would like the handle the form with a regular POST request instead of AJAX. |
ReactFormField
Most props provided to ReactFormField
fields will automatically be passed down and extended to the native input element and also the template component. Below explains custom and modified ReactForm
properties and their behaviour.
| Prop | Type | Description |
| ---------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type
| text, number, tel, email, password, textarea, radio, checkbox, select
| Defines the type of input element to render. Select and textarea types will return native <select>
and <textarea>
elements, all other elements will use <input>
with the type=""
property. |
| name
| string | The unique name for the field. This name is used in the return fields array on submit/error and for validation checks. |
| id
| string | Standard unique dom id. Used to map the input field to it's label in the field template. |
| label
| string | Text used for the field label. |
| required
| boolean | If true
the field will expect a positive value in order to validate. |
| validators
| array | An array of strings representing matching validator names. The field will be validated against each validator rule in the array. Validators are detailed further here. |
| match
| string | The unique name of another field to compare and validate the value against. e.g. match="password"
will look for the field with name="password"
and not validate until the values match. |
| info
| string | A string of informational text that the default field template supports. The info text will be rendered just underneath the input and input errors area of the template.
| errorMessages
| object | An object of keyed custom error messages that will override the default validator errors matching the name. e.g. errorMessages={{required: "Please enter your email address."}}
will use the error string when the required
validation fails and errorMessages={{required: "Please select an option.", email: "Use a real email eh!"}}
will use the email
error message when the field fails the email
validator name. |
| hideErrors
| boolean | A boolean to toggle the showing of error messages for the field. Useful if you are just intending to use an error style over the info
text prop instead of showing the error message when invalid.
| children
| array | Child elements are supported only for type="select"
fields and are intended to be standard select options. e.g. <option value="first">First option</option>
|
| fieldComponent
| component | A react template component that will override the default Field component. More info on custom field template components here. |
Default Validators
The ReactFormFields
can use the following default validators out of the box. Check the validator files in the /src/validators
directory of the main repo for more information on the validation and regex used.
Email
Validates the field against a valid email pattern regex.
<ReactFormField
validators={["email"]}
>
Password
Validates the field to make sure it only contains at least 8 characters long, includes 1 uppercase letter, 1 lower case letter, 1 number and 1 special character.
<ReactFormField
validators={["password"]}
>
Name
Validates the field to make sure it only contains letters (A-Z) and spaces.
<ReactFormField
validators={["name"]}
>
Digits
Validates the field to make sure it only contains digits (0-9).
<ReactFormField
validators={["digits"]}
>
Mobile
Validates the field to make sure it follows an Australian mobile phone number regex.
<ReactFormField
validators={["mobile"]}
>
Date
Validates the field to make sure it follows a date regex pattern.
<ReactFormField
validators={["date"]}
>
Postcode
Validates the field to make sure it a standard Australian postcode format and range.
<ReactFormField
validators={["postcode"]}
>
Custom Validators
Custom validation rules can be created and passed to the <ReactForm>
component as an array via the validators
prop.
const customValidators = [
{
ID: "ukpostcode",
validate: input => {
var ukPostalRegex = /^[A-Z]{1,2}[0-9]{1,2} ?[0-9][A-Z]{2}$/i;
return ukPostalRegex.test(input.value);
},
error: "Please make sure this is a valid UK postcode."
}
]
<ReactForm
validators={customValidators}
onSuccess={this.handleFormValidated.bind(this)}
onError={this.handleFormError.bind(this)}
>
<ReactFormField
type="text"
name="uk_postcode"
id="postuk_postcodeode"
label="Postcode (UK)"
required={true}
validators={["ukpostcode"]}
/>
Validator Pattern
Each validator is represented as an object with 3 keys.
{
ID: "ukpostcode",
validate: input => {
var ukPostalRegex = /^[A-Z]{1,2}[0-9]{1,2} ?[0-9][A-Z]{2}$/i;
return ukPostalRegex.test(input.value);
},
error: "Please make sure this is a valid UK postcode."
}
ID : string
A string representing the validator name and used to identify which fields to validate against.
validate : function
A function that takes the input element as an argument, processes it and returns true
if valid.
error : string
The default error message that will be shown to the user.
Field Template Component
Each instance of ReactFormField
should return the processed input and props to a template component that will handle the layout of the field.
Out of the box a default template component will be used for all available field types to handle different structual markup (checkbox, radio, select and textarea fields). For reference the default component can be viewed at /src/components/Field.js
in the main repo.
The base component template will also require an import of the SCSS from the module to mainly handle structual styling of the field template.
Below is an example of the rendered markup from a text type input which is invalid -
Initialise the field in react
<ReactFormField
type="text"
name="firstName"
id="firstname"
label="First Name First"
placeholder="First Name"
required={true}
validators={["name"]}
errorMessages={{
required: "Please enter your first name."
}}
/>
Rendered output markup (in an invalid state with an error message)
<div class="react-form__field react-form__field--text is-incomplete is-invalid">
<label for="firstname">
<div class="react-form__field__label">
<div class="react-form__field__label__inner">First Name First</div>
</div>
<input
type="text"
name="firstName"
id="firstname"
label="First Name First"
placeholder="First Name"
value=""
errors="Please enter your first name."
/>
</label>
<div class="react-form__field__errors">
<div class="react-form__field__errors__item">
Please enter your first name.
</div>
</div>
</div>
Custom Field Template Component
The ReactForm
and ReactFormField
components both provide support for passing a custom template component via the fieldComponent
prop. Passing the component to at the parent ReactForm
level will use this field for all child ReactFormField
fields, whereas passing the component at the ReactFormField
level will just use the template for that specific field.
Example Component:
const MyCustomFieldTemplate = props => {
return (
<div
className={`my-custom-field-template
${props.classes.inheritedClasses}
${props.classes.isDisabled}
${props.classes.isIncomplete}
${props.classes.isFocused}
${props.classes.isValid}
${props.classes.isInvalid}
${props.classes.hasValue}
`}
>
<label htmlFor={props.id}>{props.label}</label>
{/* input element (input, select, textarea) */}
{props.inputElement}
{/* errors */}
{props.showErrors && props.errors && props.errors.length ? (
<div className={`my-custom-field-template__errors`}>
<div className={`my-custom-field-template__errors__item`}>
{props.errors[0]}
</div>
</div>
) : null}
</div>
);
};
Use for all ReactFormField fields
<ReactForm
onSuccess={this.handleFormValidated.bind(this)}
onError={this.handleFormError.bind(this)}
fieldComponent={MyCustomFieldTemplate}
>
Use for a specific ReactFormField field
<ReactFormField
type="text"
name="firstName"
id="firstname"
label="First Name First"
placeholder="First Name"
required={true}
validators={["name"]}
errorMessages={{
required: "Please enter your first name."
}}
fieldComponent={MyCustomFieldTemplate}
/>
Available fieldComponent
props
All props applied to ReactFormField
will be passed down to the template component provided. In addition a number of special props are added to assist with building out the template logic.
inputElement
: element
The input element itself (input, textarea, select), this will let you decide where to render the element inside your template.
// template component
return(
<label htmlFor={props.id}>{props.label}</label>;
{/*input element*/}
{props.inputElement}
)
classes
: object
An object of conditional state classes detailing the current validation and interaction state of the input -
classes: {
hasValue: "";
inheritedClasses: "";
isDisabled: "";
isFocused: "";
isIncomplete: "is-incomplete";
isInvalid: "";
isValid: "";
}
errors
: array
An array error message for the corresponding current validation errors
errors: ["This field is required.", "Please enter some digits."];
showErrors
: boolean
A boolean detailing where to visually show errors for this field. Returned on bluring of an field input or when the form action is submitted.
valid
: boolean
A boolean representing if the input is completly valid and will submit.
passwordToggleBtn
: element
The prebound password toggle button. Only passed for type="password"
inputs.
Developing
JS files for this module are found in the root src
folder. The entry point can be found at src/index.js
. The module also includes base styles inside the scss/
folder.
To preview and test the module whilst developing there is also an included test react project under test-app
. This app is generated from create react app and is not included in the outputted npm package.
Publishing
After making changes, a commit should be created and, if required, merged back into the develop
branch. The version number should then be incremented using one of the npm version
commands outlined below. This will ensure that a new commit is created and tagged with the new version number.
npm version patch
- Minor bug fixes/changes
npm version minor
- For new backwards compatible features
npm version major
- For any backwards incompatible changes
Finally, publish your changes to NPM using npm publish
. This will also push all changes and tags to the develop
branch on origin
.