Form

Let's have a look of what using your themes and writing some actual forms looks like.

Controlled vs uncontrolled forms

When writing your form you need to decide whether your form should be controlled or uncontrolled. I.e do you need to keep track of all the form changes via onFieldChange and inform the form via a changed model? Or is it sufficient to maybe provide an initialModel and only get to know the field values in the onSubmithandler?

In most cases the less complex uncontrolled forms will be fine. But sometimes you need to be aware of the field values to change the render output accordingly. This is when controlled forms come in handy.

Uncontrolled form example

import React from 'react'
import {Form, ReformContext} from 'react-reform'
import defaultValidations from 'react-reform/opt/validations'
import {Text} from 'react-reform/opt/inputs'
import defaultTheme from '../default-theme'

export default class ExampleForm extends React.Component {

  handleSubmit = (data) => {
    console.log('data', data)
  }

  render() {
    return (
      <ReformContext themes={{default: defaultTheme}} validations={defaultValidations}>
        <div>
          <h4>Form</h4>
          <Form onSubmit={this.handleSubmit}>
            <Text name="firstName" label="First Name" isRequired/>
          </Form>
        </div>
      </ReformContext>
    )
  }
}

See it in action

Form

is required
Check your console to see the submitted value

Controlled form example

import React from 'react'
import {Form, ReformContext} from 'react-reform'
import defaultValidations from 'react-reform/opt/validations'
import {Text} from 'react-reform/opt/inputs'
import defaultTheme from '../default-theme'

export default class ExampleForm extends React.Component {

  state = {
    model: {firstName: null}
  }

  handleSubmit = (data) => {
    console.log('data', data)
  }

  handleFieldChange = (fieldName, value) => {
    this.setState({model: {...this.state.model, [fieldName]: value}})
  }

  render() {
    const {model} = this.state

    return (
      <ReformContext themes={{default: defaultTheme}} validations={defaultValidations}>
        <div>
          <h4>Hello {model.firstName || 'there'}!</h4>
          <Form model={model}
            onFieldChange={this.handleFieldChange}
            onSubmit={this.handleSubmit}
          >
            <Text name="firstName" label="First Name" isRequired/>
          </Form>
        </div>
      </ReformContext>
    )
  }
}

See it in action

Hello there!

is required
Check your console to see the submitted value

Form props

theme: (string|themeObj)

Defaults to 'default'. You may either pass a string referencing a theme name that you defined via ReformContext or you may pass a theme object created via createTheme.

onSubmit: fn(data, event) => (Promise?)

The onSubmit handler will be called once the form was submitted and all fields' validations returned true.

The data is an object with the fields' names as keys and their values as the value.

You may return a promise to indicate to the theme that there's no result yet. The status within the renderFormFn will be 'pending'.

If the promise gets resolved the form gets reset and a 'success' status will be set.

You may also reject the promise. You have two options. If you know the field(s) that led to the error you may reject like this: reject({fieldName: 'is not unique'}). If the error is more generic, reject with a string or react element: reject(<span>the server responded with a <b>{code}</b> message</span>)

initialModel (optional) uncontrolled forms only.

You may pass in initial data in the form of an object mapping field name to values. These values will be used when the form is mounted or reset.

model controlled forms only.

Passing a model prop signals to the form that it's an controlled form. It expects an object mapping field name to values. Field values won't be changed unless you explicitely change the model.

onFieldChange: fn(fieldName, value) controlled forms only.

This handler allows you to react to fieldChange request. Most typically it looks like the one form the controlled form example above.

You may return false to indicate that no change has happened. This will prevent the input from becoming isDirty.

children

Pass your inputs here. It's perfectly fine to pass in non-inputs here as well. So a form like this will work:

<Form onSubmit={this.handleSubmit} theme="dark">
  <Text name="name" isRequired/>
  <hr/>
  <button type="button" onClick={this.toggleSpecial}>
    toggle special
  </button>
  {this.state.showSpecial && (
    <div className="special">
      <Text name="price" isRequired/>
    </div>
  )}
</Form>

Form instance methods

You may attach a ref prop to the form. This ref officially supports some methods you might want to take advantage of.

reset()

Sets the form inputs to an untouched state.

checkForErrors() => ({hasErrors, firstInvalidFieldName})

In case you'd like to validate the form without submitting it. Call this method. You can use the firstInvalidFieldName to focus the relevant input (see below).

focusField(fieldName)

Calls focuses the input by executing the focusFn(node) method according to it's definition on the WrapInput component.

React Reform is brought to you by Codecks. Suggest edits for these pages on GitHub