React Components

New in version 0.10.

To help you get started quickly, newforms provides some React components to handle instantation and rendering of Forms and FormSets.

For the basic scenario of displaying form fields in the order they were defined, these may be all you need to handle rendering your forms.

RenderForm

This component renders a Form as a list of “rows” – one for each field.

It handles the generic use case for form rendering:

  • Whole-form error messages are displayed at the top.
  • Each visible field in the form is displayed in the order fields were defined.

It can also take care of some of the details of creating a Form instance and re-rendering when the form’s state changes for you.

<RenderForm form={MyForm} ref="myForm"/>

Form options

If form construction options are passed as props to RenderForm, they will be passed on to the Form constructor when creating an instance.

For example, if you need to display more than one of the same Form, you need to specify a prefix to give them a unique namespace, so pass a prefix prop like so:

var ParentForm = forms.Form.extend({
  name: forms.CharField(),
  dob: forms.DateField({label: 'Date of birth'})
})
<fieldset>
  <legend>Parent 1</legend>
  <RenderForm form={ParentForm} prefix="parent1"/>
</fieldset>
<fieldset>
  <legend>Parent 2</legend>
  <RenderForm form={ParentForm} prefix="parent2"/>
</fieldset>

Getting the Form instance

When passing RenderForm a Form constructor, give it a ref prop so you can use its getForm() method to access the Form instance it manages for you.

For example, when handling submission of a form:

render: function() {
  return <form onSubmit={this._onSubmit}>
    <forms.RenderForm form={MyForm} ref="myForm"/>
    <button>Submit</button>
  </form>
},

_onSubmit: function(e) {
  e.preventDefault()
  var form = this.refs.form.getForm()
  var isValid = form.validate()
  if (isValid) {
    // ..
  }
}

Other rendering scenarios

For the sake of being a complete default rendering implementation, RenderForm also handles some less common scenarios:

  • Displaying error messages related to hidden fields.
  • Rendering hidden fields.
  • Displaying a progress indicator if the form has asynchronous whole-form validation pending completion.

RenderForm props

Note

A ReactCompositeComponent is what you get back when you call React.createClass()

form
type:Form or Function (a Form constructor)

The Form to be rendered – can be a constructor or an instance.

If you pass a Form constructor, the component will instantiate it for you. Form construction options may also be passed to RenderForm as additional props.

If you pass a Form instance, make sure you set up its onChange() in such a way that it will also re-render the <RenderForm/> component when the form changes.

component
type:ReactCompositeComponent or String (an HTML tag name)

The component used to wrap all the form’s rows – defaults to 'div'.

className
type:String

If provided, this prop will be passed to the wrapper component containing all the form’s rows.

row
type:ReactCompositeComponent

The component used to render each form row – defaults to FormRow.

rowComponent
type:ReactCompositeComponent or String (an HTML tag name)

The tag name or component used to wrap each form row. Defaults to 'div'.

This is passed as a component prop to the component in the row prop.

progress
type:ReactCompositeComponent or Function

Used to render what’s displayed if the form has an async clean() method which is pending completion.

This will also be passed to the component in the row prop when rendering.

Form construction options
All the options which be passed when instantiating a Form can be passed as props to RenderForm for use when you pass a Form constructor as the form prop.

RenderForm methods

getForm()
Returns the Form instance being rendered by the component.

FormRow

This component handles rendering a single form “row”. RenderForm uses this to render rows by default; it will either:

  1. Wrap some given content (such as a list of error messages) as a row, or:
  2. Use a field’s rendering helper to generate a row for the field, with a label, user input, error messages and help text, as necessary.

FormRow props

content
type:Any

If given, will be used for the entire contents of the row.

bf
type:BoundField()

If given and content is not given, this Field rendering helper will be used to create contents for a Field row.

component
type:ReactCompositeComponent or String (an HTML tag name)

The component used to wrap the row contents. Defaults to 'div'.

className
type:String

If provided, this prop will be passed to the wrapper component for the row.

hidden
type:Boolean

If true, the row container ReactElement will be given a display: none style – defaults to false.

progress
type:ReactCompositeComponent or Function

Used to render what’s displayed if the form has async clean<Field>() method which is pending completion.

RenderFormSet

This component handles the generic use case for FormSet rendering, using RenderForm to render each form in a formset one after the other.

It can also take care of some of the details of creating a FormSet and re-rendering when form state changes.

<RenderFormSet form={MyForm} extra="3" ref="myFormset"/>

<RenderFormSet formset={MyFormSet} ref="myFormset"/>

RenderFormSet props

form
type:Function (a Form constructor)

If you pass a Form constructor, the component will instantiate a FormSet for you.

FormSet constructor options may be passed as additional props to RenderFormSet.

Note

When a form prop is passed, use of the formset prop changes. If also provided, it must be a FormSet constructor to be extended from.

formset
type:FormSet or Function (a FormSet constructor)

The FormSet to be rendered – can be a constructor or an instance.

If you pass a FormSet constructor, the component will instantiate it for you. FormSet construction options may also be passed to RenderFormSet as additional props.

If you pass a FormSet instance, make sure you set up its onChange() in such a way that it will also re-render the <RenderFormSet/> component when one of its forms changes.

component
type:ReactCompositeComponent or String (an HTML tag name)

The component used to wrap the formset’s contents. Defaults to 'div'.

className
type:String

If provided, this prop will be passed to the wrapper component for the formset.

formComponent
type:ReactCompositeComponent or String (an HTML tag name)

The component used to wrap each form. Defaults to 'div'.

This is passed as a component prop to RenderForm.

row & rowComponent
These are as defined above for RenderForm, which they are passed to.
progress
type:ReactCompositeComponent or Function

Used to render what’s displayed if the formset has an async clean() method which is pending completion.

This will also be passed to RenderForm.

useManagementForm
type:

Boolean

If true, hidden fields from the FormSet’s management form will be rendered. Defaults to false.

These fields are usually only required if you will be performing a regular form submission which will be processed by newforms on the server.

RenderFormSet methods

getFormset()
Returns the FormSet instance being rendered by the component.

Custom rendering with props

The bundled React compoents offer a degree of customisation via their props.

You can use the component, className and rowComponent props to customise the containers:

<RenderForm form={ParentForm}
   component="ul"
   className="parent"
   rowComponent="li"
   autoId={false}
/>

Which renders as:

<ul class="parent">
  <li>Name: <input type="text" name="name"></li>
  <li>Date of birth: <input type="text" name="dob"></li>
</ul>

You can also customise how form rows are generated by passing a custom React component to the row prop.

<RenderForm form={ParentForm} row={MySpecialFormRow}/>

Note

Keep in mind when implementing a custom row component that it will receive props as per those described for FormRow.

Custom rendering with a child component

If you want to implement custom form rendering with your own React component while still making use of RenderForm to instantiate the form and set up automatic validation and redisplay, pass a component as the only child of RenderForm.

Warning

Passing more than one child component to RenderForm will result in an Error.

RenderForm wil then clone your component and pass the Form instance it manages as a form prop.

Note

This method of implementing custom rendering by passing a prop is temporary. An upcoming change to React’s currently (as of React 0.12) undocumented context feature will remove the need to pass props down the chain of components for this sort of scenario.

For example, this is how newforms-gridforms implements a custom grid layout:

<RenderForm form={ParentForm}>
  <GridForm>
    <Section name="Parent">
      <Row>
        <Field name="name"/>
        <Field name="dob"/>
      </Row>
    </Section>
  </GridForm>
</RenderForm>

Custom async progress rendering

By default, when async validation is in progress, each of the React components newforms provides will render a <progress> element with fallback “Validating...” text. However, the <progress> element doesn’t currently lend itself to extensive customisation via CSS, especially cross-browser.

To customise this, each component takes a progress prop which can take a function or React component which will be used to indicate an in-progress async validation.

For example, either of the following could be passed as the progress prop to display a spinner image instead:

var InProgress = React.createClass({
  render() {
    return <span>
      <img src="/img/spinner.gif" alt=""/> Validating&hellip;
    </span>
  }
})

function inProgress() {
  return <span>
    <img src="/img/spinner.gif" alt=""/> Validating&hellip;
  </span>
}
<RenderForm form={MyForm} ref="myForm" progress={InProgress}/>