react-material-ui-form
About
react-material-ui-form is a React wrapper for Material-UI form components. Simply replace the <form>
element with <MaterialUIForm>
to get out-of-the-box state and validation support as-is. There's no need to use any other components, alter your form's nesting structure, or write onChange handlers.
Validation is done with validator.js but you can extend/customize validation messages, validators, and use your own validation logic too. Steppers, dynamic array fields and custom components are also supported.
use and requirements
- requires React 16.3.0 or newer
- supports official and unofficial Material-UI fields (other input elements are rendered without state/validation support)
- every input field must have
value
andname
props - every input field should NOT have
onChange
andonBlur
props (unless you need custom field-specific logic) - add a
data-validators
prop to any input field (or FormControl / FormControlLabel) to specify validation rules
extra validators
react-material-ui-form extends validator.js validators with the following validators:
- isAlias
/^[a-zA-Z0-9-_\.]*$/i
- isDate
- isNumber
/^([,.\d]+)$/
- isRequired
value.length !== 0
- isSerial
/^([-\s\da-zA-Z]+)$/
- isSize
value >= min && value <= max
- isTime
- isLength(min,max)
[{ isLength: { min: 2, max: 50 } }]
Supported field components
- TextField
- TextField { select }
- TextField { multiline, textarea }
- Checkbox
- RadioGroup
- Radio
- FormControlLabel (control prop)
- FormLabel
- InputLabel
Note
Currently this package will support only till Material-UI v3
Setup
install
npm install --save react-material-ui-form
demo
$ git clone https://github.com/voletiswaroop/react-material-ui-form.git
$ cd react-material-ui-form
$ npm install && npm run dev
Props
Form props (optional):
Prop | Description | Default |
---|---|---|
[class] [string] | Sets className attribute to the form |
|
[id] [string] | Sets id attribute to the form |
|
[name] [string] | Sets name attribute to the form |
|
[action] [string] | Sets action attribute to the form |
|
activeStep [number] | Use together with onFieldValidation for better Stepper support |
|
autoComplete [string] | Sets form autoComplete prop. Accepts one of ["on", "off"] | "off" |
disableSubmitButtonOnError [boolean] | Disables submit button if any errors exist | true |
onFieldValidation [func] | Returns @field and @errorSteps (if activeStep prop is provided) on field validation |
|
onSubmit [func] | Returns @values and @pristineValues on form submission | |
onValuesChange [func] | Returns @values and @pristineValues on field value change | |
validation [object] | Object specifing validation config options (prefixed below with ↳) | |
↳ messageMap [object] | A key-value list where the key is the validator name and the value is the error message. Is exposed as a react-material-ui-form export parameter | object |
↳ messageKeyPrefix [string] | Optional prefix to apply to all messageMap keys. If specified, field validator names will automatically be appended the prefix | "" |
↳ requiredValidatorName [boolean, string] | Specifies the validator name and matching messegeMap key for required fields. To disable and rely on the native required field prop, set to false |
"isRequired" |
↳ validate [func] | Overrides the internal validate method. Receives the following parameters: @fieldValue, @fieldValidators, and @...rest (where @...rest is the validation prop object) | func |
↳ validators [object] | Defaults to an extended validator.js object. Is exposed as a react-material-ui-form export parameter | object |
↳ validateInputOnBlur [boolean] | Makes text input validations happen on blur instead of on change | false |
validations [object] | Validations to pass to the form (i.e. from the server). Should be an object with keys representing field name props and values as arrays of field error messages. The first error message will be displayed per field |
Field props:
Prop | Description | Required |
---|---|---|
value [any] | The value of the field. If empty set an empty string | Yes |
name [string] | The name of the field | Yes |
data-validators [string, array[object]] | Validators to apply to the field. Multiple validator names can be specified with a comma-delimited string | |
onBlur [func] | A custom handler that will be called after the field's onBlur event. Provides @value/checked, @field and @event parameters |
|
onChange [func] | A custom handler that will be called after the field's onChange event. Provides @value/checked, @field and @event parameters |
Other props:
Prop | Value | Description |
---|---|---|
deletefieldrow [string] | Field name prop up to and including the row index (i.e. rooms[2]) | Add to button components that use onClick to remove any array field rows |
Material-UI form production build classnames conflict issues
To avoid default material-ui production build classnames conflict issues include your entire form inside Example: Nested fields
Examples
Nested fields:
import MaterialUIForm from 'react-material-ui-form'import JssProvider from 'react-jss/lib/JssProvider'; Component { // get all values and pristineValues on form submission } { // the form will update the field as usual, and then call this handler // if you want to have complete control of the field, change the "value" prop to "defaultValue" } { // the form will update the field as usual, and then call this handler // if you want to have complete control of the field, change the "value" prop to "defaultValue" } { return <JssProvider> <MaterialUIForm => <TextField ="Name" ="text" ="name" ="" ="isRequired,isAlpha" = /> <fieldset> <FormControl> /* form label is required here to perform default validations */ <FormLabel ="legend">I love React material UI form</FormLabel> <FormGroup =''> <FormControlLabel = ='I love React material UI form'/> </FormGroup> </FormControl> <FormControl > <InputLabel>Age</InputLabel> <Select ="" ="age"> <MenuItem =""><em>Please select your age ...</em></MenuItem> <MenuItem =>Teens</MenuItem> <MenuItem =>Twenties</MenuItem> <MenuItem =>Thirties</MenuItem> <MenuItem ="40+">Fourties +</MenuItem> </Select> <FormHelperText>Some important helper text</FormHelperText> </FormControl> </fieldset> <FormControl> <FormLabel ="legend">Gender</FormLabel> <RadioGroup ="Gender" ="gender" ="male"> <FormControlLabel ="female" = ="Female" /> <FormControlLabel ="male" = ="Male" /> </RadioGroup> </FormControl> <Button ="raised" ="reset">Reset</Button> <Button ="raised" ="submit">Submit</Button> </MaterialUIForm> </JssProvider> }
Custom validators:
import Form messageMap validators from 'react-material-ui-form/dist/validation/index'; validators value === 'borat'const customMessageMap = Object Component { // get all values and pristineValues on form submission } { return <MaterialUIForm = => <TextField ="Write anything..." ="text" ="trickster" ="" ="this is not a trick" ="isBorat" /> <Button ="raised" ="submit">Submit</Button> </MaterialUIForm> }
Custom validation messages:
const customFormMsg = ObjectComponent { // get all values and pristineValues on form submission } { return <MaterialUIForm = => <TextField ="Name" ="text" ="FirstName" ="Name" ="isLength" /> <TextField ="Email" ="text" ="Email" ="abc@xyz.com" ="isRequired,isEmail" /> <Button ="raised" ="submit">Submit</Button> </MaterialUIForm> }
Custom validation logic:
import MaterialUIForm from 'react-material-ui-form' { const fieldValidations = fieldValidators return fieldValidations} const validationOptions = genericMessage: 'yeah... *tisk*' Component { // get all values and pristineValues on form submission } { return <MaterialUIForm = => <TextField ="Whatever you write isn't gonna be good enough" ="text" ="test" ="" ="whatever - our custom validator will ignore this" /> <Button ="raised" ="submit">Submit</Button> </MaterialUIForm> }
Server validations:
import MaterialUIForm from 'react-material-ui-form' const mockServerValidations = name: code: 'isInvalid' message: 'such invalid...' Component state = mockServerValidations { let validations = name: message: 'such WOOOOOOOOOW...' } { // get all values and pristineValues on form submission } { return <MaterialUIForm = => <TextField ="Name" ="text" ="name" ="doge" /> <Button ="raised" ="submit">Submit</Button> </MaterialUIForm> }
Form autoComplete and "on error" submission:
import MaterialUIForm from 'react-material-ui-form' Component { // get all values and pristineValues on form submission } { return <MaterialUIForm ="on" = => <TextField ="Name" ="text" ="name" ="doge" ="isInt" /> <Button ="raised" ="submit">Submit</Button> </MaterialUIForm> }
Getting form values on field update:
import MaterialUIForm from 'react-material-ui-form' Component { // get all values and pristineValues when any field updates } { // get field object when its validation status updates } { // get all values and pristineValues on form submission } { return <MaterialUIForm = = => <TextField ="Name" ="name" ="doge" /> <Button ="raised" ="submit">Submit</Button> </MaterialUIForm> }
Stepper:
import Stepper Step StepLabel from 'material-ui/Stepper'import MaterialUIForm from 'react-material-ui-form' { return 'Step 1' 'Step 2' } Component state = activeStep: 0 errorSteps: { this } { this } { // get all values and pristineValues on form submission } { this } { const steps = const activeStep = thisstate return <div> <Stepper = > steps </Stepper> <MaterialUIForm = = => activeStep === 0 && <React.Fragment> <TextField ="Name" ="name" ="" /> <Button ="raised" =>Next</Button> </React.Fragment> activeStep === 1 && <React.Fragment> <TextField ="Address" ="address" ="" /> <Button ="raised" =>Back</Button> <Button ="raised" ="submit">Submit</Button> </React.Fragment> </MaterialUIForm> </div> }
deletefieldrow
prop on the "Remove Row" button):
Dynamic array fields (notice the import MaterialUIForm from 'react-material-ui-form'import formData from 'form-data-to-object' Component state = rows: _id: _ onSubmitValues: null { const rows = thisstate rows this } { const rows = thisstate if rowslength > 1 rows this } { // you can parse values to turn: // rows[0][label]: "label" // into: // rows: [{ label: "label" }] const parsedValues = formData } { const steps = return <MaterialUIForm => thisstaterows <Button ="raised" =>Add row</Button> <Button ="raised" ="primary" ="submit">Submit</Button> </MaterialUIForm> }
Custom components with custom handlers:
import MaterialUIForm from 'react-material-ui-form' Component { console } { return <div> <MaterialUIForm> 'Upload file: ' <input ="image/*" = ="raised-button-file" ="file" = /> <label ="raised-button-file"> <Button ="raised" ="span">Upload</Button> </label> </MaterialUIForm> </div> }
Contributing
This is a new project and contributions are welcome so feel free to open an issue or fork and create a pull request. Collaborators are also welcome - please send an email to swaroop.voleti@gmail.com.
License
This project is licensed under the terms of the MIT license.