Isomorphic form-handling for React
Select
and SelectMultiple
no longer render selected
attributes on their options, which was causing a warning message. React 0.14 now handles creating these in server-generated markup via parent context.RenderForm
, the Form instance is now available via a form
context variable due to React 0.14 parent context.Changed method of detecting if we're running in the browser to avoid false positives when browserify/webpack insert process
shims into browser bundles.
A false positive can result in an Error
being thrown when validating a client-side FormSet
(#75)
See the Upgrade Guide for instructions on upgrading to this release from the previous version.
RenderForm
no longer depends on having React.addons.cloneWithProps()
available for custom rendering, due to new React.cloneElement()
top-level
API.formsetFactory()
.See the Upgrade Guide for instructions on upgrading to this release from the previous version.
BaseForm
to Form
, changing the top-level API - this has the same
behaviour as the currently-exported forms.Form
.BaseFormSet
to FormSet
, changing the top-level API.util.formData()
with the
get-form-data module -
formData()
has been renamed to getFormData()
.Form
, FormSet
, fields, widgets, React
components, ValidationError
...) can be required with
require('newforms/<modulename>')
- this makes it possible to reduce the size
of your own browser bundles by requiring only what you use.Field
argument: field.widgetAttrs
- this allows you to
provide additional widget attributes without having to redefine the entire
widget (docs) (#62)Form.prototype.prefixFormat
('{prefix}-{name}'
) and
FormSet.prototype.prefixFormat
('{prefix}-{index}'
) to define how prefixes
are generated. These can be overridden when extending these components to
customise now field names are generated when prefixes are used
(example) (#70)formsetFactory()
options to FormSet
proper (API docs)
FormSet
can now be constructed directly, setting all formset-specific options for the instance instead of having to extend it,FormSet.extend()
can now be used directly to preconfigure a FormSet
constructor with the Form
constructor to be used and any other formset
options.FormSet
options can now be overridden when constructing a FormSet
.FormSet
is constructed without a Form
constructor.FileField
cleaned data is now a native File
object, when the browser
supports it (docs) (#61)
multiple
argument for FileField
- cleaned data will be a list of
File
objects.File
object is available.NumberInput
to make use of them
(#59)DecimalField
now handles all-zero inputs correctly - it was cleaning them
to an empty string (#57)Select
widgets no longer generate React dev-mode warnings about unique key
props (#68)formsetFactory()
is deprecated in favour of using FormSet.extend()
to
create a FormSet with defaults for the same options and any custom methods
required.Form
rendering methods (render()
, asTable()
, asDiv()
and asUl()
).FormSet
rendering methods (render()
, asTable()
and
asDiv()
).Major features in 0.10 are support for asynchronous validation and new React components for default rendering.
clean()
and clean<FieldName>()
methods can now use asynchronous validation - defining them with a single parameter will let newforms know they will be asynchronous: There is a bunch of new API on Forms, FormSets and BoundFields
cleanUsername: function(cb) {
// ...
}
form.validate()
now takes an additional callback argument which is required if a Form or FormSet has async validation.
Default rendering now includes a <progress>
element on fields, forms and formsets which have pending asynchronous validation.
Newforms now provides RenderForm
and RenderFormSet
React components for default Form and FormSet rendering:
<RenderForm form={MyForm} ref="myForm"/>
Default rendering methods on Forms and FormSets (.render()
, .asTable()
, .asDiv()
, .asUl()
) are now deprecated and will be removed in the next release.
formset.asUl()
- it never appeared properly due to the management
Form.formset.cleanedData()
to no longer includes cleanedData
from incomplete
extra forms.cleanedData
by returning a value from a Form's
clean<Name>()
or clean()
method.RenderForm
, FormRow
and RenderFormSet
components for default
rendering.
RenderForm
's custom rendering support.clean()
and clean<Field>()
validation methods can now be
specified with the signature (callback)
if they need to perform
asynchronous validation.
(err, validationError)
.clean()
will not be called until other fields - or just fields it
depends on, if configured - have been cleaned, synchronously or
asynchronously.form.validate()
and formset.validate()
now take a callback argument,
which is required if the Form or Formset has custom async validation
configured - validate()
can be used as normal for Form and Formsets
without async validation.
(err, isValid, cleanedData)
.form.isAsync()
/ formset.isAsync()
- true
if a form/formset has custom
async validation.form.isPending()
/ formset.isPending()
- true
if a form/formset has
pending async validation.form.nonFieldPending()
/ formset.nonFieldPending()
- true
if async
validation of a form/formset's clean(cb)
method is pending.boundField.isPending()
- true
if a field has a pending async validation.isFormAsync(Form)
- true
if a Form constructor's prototype has async
validation methods.<progress>
indicators are now displayed by default rendering methods:
optionalCssClass
- used for optional fieldspendingCssClass
- used for fields with pending async validationboundField.helpTextTag()
to expose the mechanism for rendering raw
HTML.boundField.status()
to get a field's status as a string
(pending/error/valid/default).fromJSON()
factory functions to ErrorList
and ErrorObject
constructors and fromJSON()
instance methods. These can be used to rehydrate
an ErrorObject
on the receiving end when form.errors()
is transferred as
JSON. This assumes the structure created by these objects' toJSON()
methods.form.setErrors()
to set an ErrorObject
with errors from another
source.ErrorObject
can now be passed as an errors
option when creating a form
instance, to redisplay a form with errors from another source. This prevents
the form's own validation from running if the form has input data
and
isValid()
or errors()
are called during rendering.render()
, asTable()
, asDiv()
and asUl()
) are
deprecated in favour of using React components for rendering - RenderForm
now provides default rendering.render()
, asTable()
and asDiv()
) are
deprecated in favour of using React components for rendering - RenderFormSet
now provides default rendering.form/formset.validate()
will trigger a re-render, as it looks like forceUpdate()
just enqueues a
future re-render.form.isComplete()
is now false
if there is any pending async validation,
even if all required fields currently have cleaned data.'auto'
validation, this prevents the default onBlur
event from re-running the same validation as the default onChange
.onBlur
:
form.addError()
to no longer add duplicate error messages for the
same field. This can happen if onChange
validation which runs repeatedly
adds errors to a field other than that which triggered the validation, using
addError()
.rows
attribute for a Textarea
changed from 10 to 3.displayName
property if a Form has one.onStateChange
argument to Form and FormSet constructors has
been removed - use onChange
instead.Fixed in this release:
Form.extend()
is no longer mutated.(For an alternative view of new features/changes, see the Development Wiki)
This release brings a bunch of sanity improvements (auto validation by default, better basic validation API) and improvements to FormSets which just about make them usable on the client (see Dinner Time! for an example).
__mixins__
property rather than
__mixin__
.form.validate()
to no longer call back to re-render -- this
was convenient for single forms, but results in multiple updates when
processing multiple forms. Re-rendering must now be triggered manually if
onSubmit validation fails.formset.cleanedData()
to no longer includes cleanedData
from unmodified
extra forms.onChange
to a Form or FormSet now implies validation: 'auto'
.form.notEmpty()
to determine when required fields in an extra
FormSet form become truly required.formset.validate([form])
-- equivalent to the Form version, use to
set a formset's data from a <form>
or to force full validation of its
current input data.formset.removeForm(index)
to remove extra forms from a FormSet. It
will also call back to trigger a re-render when possible.errorlist#first()
for conveniently getting just the first validation
error message.formset.addError()
for adding non-form errors outside of clean()
.form.validate([form])
so the argument is optional - it can now be
used to force full validation of a form with its current input data.clean()
functions can now specify which fields they make use of for
cross-field validation: clean: ['field1', 'field2', function() {}]
. When
provided, clean()
will only be called during partial form updates (e.g.
onChange
handling) if one of the specified fields is affected.onStateChange
argument to Form and FormSet constructors -- use
onChange
instead. onStateChange
will be removed in the next version.onChange
handlers are now always attached to widgets to update input data,
regardless of controlled/validation config.formset.addAnother()
will now call back to trigger a re-render if
possible.React.createElement()
and React.createFactory()
API for ReactElement
creation.The main features for this release are the addition of interactive validation and toggleable creation of controlled components, documentation and examples here:
form.isBound
to form.isInitialRender
, which more accurately
reflects usage of this property (it was always being used in Forms as
!isBound
)form.setData()
to no longer accept prefixed data by default.
Added a prefixed
option argument which controls this and a new
setFormData()
method which replicates the old behaviour. This makes
setData()
more user-friendly for use with controlled forms.validation
option when constructing a Form, Field or FormSet.controlled
option when constructing a Form or FormSet. When
using controlled components, form widgets reflect the state of form.data
,
so you can change what's displayed in the form by updating its data.onStateChange()
callback when provided -- passed as an
option when constructing a Form or FormSet -- any time validation state may
have changed as a result of updating user input from controlled components, or
as a result of validation triggered by user interaction. This option becomes
required when using validation
or controlled
options.form.updateData(partialData)
) and
cleaning (form.partialClean(fieldNames)
) of data.form.reset(newInitial)
to reset a form back to its initial state,
optionally providing new initial data in the process.validate
option to form.setData()
to support setting incomplete
data in a controlled form without triggering required field validation errors.form.validate(<form>)
as a convenience method for retrieving and
validating input data from a <form>
-- this removes a common step when
hooking up full-form onSubmit
validation.form.isComplete()
to determine if all required fields have valid
input data when validation is being performed interactively..errorMessage()
and .errorMessages()
to BoundField as a
convenience for accessing error message strings, instead of having to go
through .errors()
and use the ErrorList API.validCssClass
in default rendering or when using
BoundField#cssClasses()
directly, if present on a form or its prototype.validateAll
utility method equivalent to
form.validate()
but for multiple Forms and/or FormSets.Widget.prototype.needsInitialValue
to allow Widgets to always
receive the initial value of a field in addition to user input to be rendered.key
property, to prevent
fields being recreated when content around them changes (e.g. new validation
errors being displayed), which makes them lose focus.cleanedData
is now always defined regardless of whether
or not any validation has been performed yet -- this makes it safe to check
for data at any time, particularly in cross-field validation.