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()
formtype: FormorFunction(aFormconstructor)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 optionsmay also be passed toRenderFormas 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.componenttype: ReactCompositeComponentorString(an HTML tag name)The component used to wrap all the form’s rows – defaults to
'div'.classNametype: StringIf provided, this prop will be passed to the wrapper component containing all the form’s rows.
rowtype: ReactCompositeComponentThe component used to render each form row – defaults to FormRow.
rowComponenttype: ReactCompositeComponentorString(an HTML tag name)The tag name or component used to wrap each form row. Defaults to
'div'.This is passed as a
componentprop to the component in therowprop.progresstype: ReactCompositeComponentorFunctionUsed 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
rowprop when rendering.- Form construction options
- All the
options which be passed when instantiating a Formcan be passed as props toRenderFormfor use when you pass a Form constructor as theformprop.
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:
- Wrap some given content (such as a list of error messages) as a row, or:
- 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¶
contenttype: Any If given, will be used for the entire contents of the row.
bftype: BoundField()If given and
contentis not given, this Field rendering helper will be used to create contents for a Field row.componenttype: ReactCompositeComponentorString(an HTML tag name)The component used to wrap the row contents. Defaults to
'div'.classNametype: String If provided, this prop will be passed to the wrapper component for the row.
hiddentype: Boolean If
true, the row container ReactElement will be given adisplay: nonestyle – defaults tofalse.progresstype: ReactCompositeComponentorFunctionUsed 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¶
formtype: Function(aFormconstructor)If you pass a Form constructor, the component will instantiate a FormSet for you.
FormSetconstructor options may be passed as additional props toRenderFormSet.Note
When a
formprop is passed, use of theformsetprop changes. If also provided, it must be a FormSet constructor to be extended from.formsettype: FormSetorFunction(aFormSetconstructor)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 optionsmay also be passed toRenderFormSetas 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.componenttype: ReactCompositeComponentorString(an HTML tag name)The component used to wrap the formset’s contents. Defaults to
'div'.classNametype: String If provided, this prop will be passed to the wrapper component for the formset.
formComponenttype: ReactCompositeComponentorString(an HTML tag name)The component used to wrap each form. Defaults to
'div'.This is passed as a
componentprop to RenderForm.row&rowComponent- These are as defined above for RenderForm, which they are passed to.
progresstype: ReactCompositeComponentorFunctionUsed to render what’s displayed if the formset has an async
clean()method which is pending completion.This will also be passed to RenderForm.
useManagementFormtype: Boolean
If
true, hidden fields from the FormSet’s management form will be rendered. Defaults tofalse.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.
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>
Changed in version 0.13: The Form instance is also available via React’s context feature as a
form context variable, allowing you to access the Form instance in nested
custom rendering components without having to manually pass it down via props.
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…
</span>
}
})
function inProgress() {
return <span>
<img src="/img/spinner.gif" alt=""/> Validating…
</span>
}
<RenderForm form={MyForm} ref="myForm" progress={InProgress}/>