html form validation,GitHub - dsheiko/react-html5-form: Form validation component to connect React.j...

React-html5-form

68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f72656163742d68746d6c352d666f726d2e7376673f7374796c653d666c6174

68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f72656163742d68746d6c352d666f726d2e7376673f7374796c653d666c6174

68747470733a2f2f636f6465636f762e696f2f67682f64736865696b6f2f72656163742d68746d6c352d666f726d2f6272616e63682f6d61737465722f67726170682f62616467652e737667

68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7465737465645f776974682d6a6573742d3939343234662e737667

712b91abc51e4ab052b5d9510e14c31e.png

With the package you don't need to re-create form validation logic every time. Instead you take full advantage of HTML5 Constraint Validation API. Besides the package expose no custom input components, instead it provides wrapper InputGroup, which binds inputs (according to configuration) in the children DOM nodes. Thus you can go with both HTML controls and 3rd-party input components.

8f788b510cc743054b39c3005aa51b21.png

Highlights

Input implementation agnostic, can be used any arbitrary input controls (HTML or 3rd-party React components)

Standard HTML5 syntax for validation constraints (like )

Can be extended with custom validators (again by using standard HTML5 API)

Can be setup for custom validation messages per input/ValidityState.Property

Form and input groups expose validity states, so you can use it to toggle scope error messages.

Form and input groups expose reference to own instances for children DOM nodes. So you can, for example, subscribe for input event and run input group validation (e.g. see On-the-fly validation)

Can maintain form state both ways: with React Context and Redux

Overview

With Form we define scope of the form. The component exposes parameters valid, error and form. The first reflects actual validity state according to states of registered inputs. The second contains error message (can be set using API). The last one is instance of the component and provides access to the API.

With InputGroup we define a fieldset that contains one or more semantically related inputs (e.g. selects day, month, year usually go togather). The group expose valid, error, errors and inputGroup variables on children Nodes. So we can automatically toggle group error message and content classList depending on them.

We register inputs within InputGroup with validate prop. There we can specify a validator function, which will extend HTMP5 form validation logic. Very easily we can provide mapping for standard validation message (translate prop).

react-html5-form.png

Installation

npm i react-html5-form

Demo

You can see the component in action at LIVE DEMO 📺

source code of example with HTML elements for inputs (styled with Bootstrap 4)

source code of example with read-made components for inputs (styled with MaterialUI.Next)

source code of example with connection to Redux

Form

Represents form

import { Form } from "react-html5-form";

Props

onSubmit - (OPTIONAL) form submit handler

onMount - (OPTIONAL) callback that gets invoked in componentDidMount(), it receives component instance as parameter

onUpdate - (OPTIONAL) callback that gets invoked when form ready (all input groups registered) and when it changes validity state. It's intended to be used with Redux to update tree state

any attributes of Form HTML element

API

scrollIntoViewFirstInvalidInputGroup() - scroll first input group in invalid state into view (happens automatically onSubmit)

checkValidityAndUpdateInputGroups() - check form validity and update every input group

checkValidityAndUpdate() - check form validity and update only form state (without updating input groups)

setError( message = "") - set form scope error message

submit() - submit form

getRef() - get Ref instance pointed to the generated FORM element. Thus if you need to access the DOM node, you go with form.getRef().current

debugInputGroups( inx = null ) - get debug info about all registered inputs, or one matching given index

Scope parameters

error - error message set with setError()

valid - form validity state

pristine - true if user has not interacted with the form yet.

submitting - true while form is being processed on submission

submitted - true after form submitted

form - link to the component API

State properties valid, pristine, submitting, submitted are also available as element data-attributes e.g. data-submitting="false"

Defining component

import React from "react";

import { render } from "react-dom";

import { Form } from "react-html5-form";

const MyForm = props => (

{({ error, valid }) => (

<>

Form content

>

)}

);

render( , document.getElementById( "app" ) );

creates wrapper for passed in children. It delegates properties to the produced HTML Element.

For example specified id ends up in the generated form.

Accessing Form API

async function onSubmit( form ) {

form.setError("Opps, a server error");

return Promise.resolve();

};

const MyForm = props => (

{({ error, valid, pristine, submitting, form }) => (

<>

{ error && (

Oh snap! {error}

)

}

Form content

Submit

>

)}

);

The API can be accessed by form reference. Besides, any handler passed through onSubmit prop gets wrapped.

The component calls setState for checkValidity prior calling the specified handler. From the handler you can

access the API by reference like form.setError. What is more, we disable submit button until the user first interaction with the form and on form submission (onSubmit is an asynchronous function / Promise; as it resolves the state propertysubmitting` set in false).

InputGroup

InputGroup defines scope and API for a group of arbitrary inputs registered with validate prop. InputGroup exposes in the scope parameters that can be used to toggle group validation message(s), group state representation and to access the component API

import { Form, InputGroup } from "react-html5-form";

Props

validate - (REQUIRED) register inputs to the group. Accepts either array of input names (to match [name=*]) or plain object out of pairs name: custom validator

// Group of a single input

// Group of multiple inputs

// Custom validator

"vatId": ( input ) => {

if ( !input.current.value.startsWith( "DE" ) ) {

input.setCustomValidity( "Code must start with DE" );

return false;

}

return true;

}

}}>

translate - (OPTIONAL) set custom messages for validation constraints (see ValidityState Properties)

...

translate={{

firstName: {

valueMissing: "C'mon! We need some value",

patternMismatch: "Please enter a valid first name."

}

}}>

tag - (OPTIONAL) define tag for the generated container HTML element (by default div)

onMount - (OPTIONAL) callback that gets invoked in componentDidMount(), it receives component instance as parameter

onUpdate - (OPTIONAL) callback that gets invoked when form ready (all input groups registered) and when it changes validity state. It's intended to be used with Redux to update tree state

any attributes of HTML element

API

checkValidityAndUpdate() - run checkValidity() and update the input group according to the actual validity state

getInputByName( name ) - access input fo the group by given input name

getValidationMessages() - get list of all validation messages within the group

checkValidity() - find out if the input group has not inputs in invalid state

getRef() - get Ref instance pointed to the generated element. Thus if you need to access the DOM node, you go with inputGroup.getRef().current

Scope parameters

error - validation message for the first invalid input

errors - array of validation messages for all the inputs

valid - input group validity state (product of input states)

pristine - true if user has not interacted with the form yet.

inputGroup - link to the component API

Basic use

tag="fieldset"

validate={[ "email" ]}

translate={{

email: {

valueMissing: "C'mon! We need some value"

}

}}>

{({ error, valid }) => (

Email address

type="email"

required

name="email"

className={`form-control ${!valid && "is-invalid"}`}

id="emailInput"

placeholder="Enter email" />

{ error && (

{error}
) }

)}

Here we define an input group with registered input matching [name=email]. We also specify a custom message for ValidityState.valueMissing constraint.

It means that during the validation the input has no value while having constraint attribute required the input group receive validation message "C'mon! We need some value" in scope parameter error.

Custom validators

"vatId": ( input ) => {

if ( !input.current.value.startsWith( "DE" ) ) {

input.setCustomValidity( "Code must start with DE." );

return false;

}

return true;

}

}}>

{({ error, valid }) => (

VAT Number (optional)

className={`form-control ${!valid && "is-invalid"}`}

id="vatIdInput"

name="vatId"

placeholder="Enter VAT Number"/>

{ error && (

{error}
) }

)}

Here we define a custom validator for vatId input (via validate prop). The validator checks if the current input value starts with "DE".

If it dosn't we apply setCustomValidity method to set the input (and the group) in invalid state (the same as of HTML5 Constraint validation API).

Group with multiple inputs

const validateDateTime = ( input ) => {

if ( input.current.value === "Choose..." ) {

input.setCustomValidity( `Please select ${input.current.title}` );

return false;

}

return true;

};

{({ errors, valid }) => (

Day

Choose...

...

Month

Choose...

...

{ errors.map( ( error, key ) => (

{error}
)) }

)}

On validation we receives errors array that contains validation messages for all the inputs registered in the group. So we can display the messages within the group container.

On-the-fly validation

Let's first define the onInput event handler:

const onInput = ( e, inputGroup ) => {

inputGroup.checkValidityAndUpdate();

};

We use checkValidityAndUpdate method to actualize validity state and update the component.

Now we subscribe the component:

validate={[ "firstName" ]}

translate={{

firstName: {

patternMismatch: "Please enter a valid first name."

}

}}>

{({ error, valid, inputGroup }) => (

First Name

pattern="^.{5,30}$"

required

className={`form-control ${!valid && "is-invalid"}`}

id="firstNameInput"

name="firstName"

onInput={( e ) => onInput( e, inputGroup, form ) }

placeholder="Enter first name"/>

{ error && (

{error}
) }

)}

Here while assigning event handler inline we delegate the instance of component to earlier created onInput function like onInput={( e ) => onInput( e, inputGroup ) }. Thus we can operate it when responding to the event.

Input

Represents input element within input group scope.

API

current - input HTML element

setCustomValidity( message = "" ) - set the input in invalid state

checkValidity() - returns boolean truthy when all the input in valid state

getValidationMessage() - get validation message considering assigned custom message if any

Connecting to Redux store

The package exposes reducer html5form, so one can connect form/input group/input states to the store:

import React from "react";

import { render } from "react-dom";

import { createStore, combineReducers } from "redux";

import { Provider } from "react-redux";

import { App } from "./Containers/App.jsx";

import { html5form } from "react-html5-form";

const appReducer = combineReducers({

html5form

});

// Store creation

const store = createStore( appReducer );

render(

, document.getElementById( "app" ) );

Thus we get package-specific state tree in the store:

react-h5-redux.png

See full example here

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值