Skip to content
insin edited this page Nov 17, 2014 · 106 revisions

Development

0.9 (latest release)

  • Changes to onChange & active validation
    • ☑ Rename onStateChange to onChange
      • ☑ Detect onStateChange, reassign to onChange and warn of deprecation in 0.9 dev version
    • ☑ Passing onChange now implies `validation: 'auto'
      • ☑ Check for both being passed and warn that it's not necessary in 0.9 dev version
    • ☑ Always hook up an onChange handler to widgets to keep form.data up to date with user input, even if it's not being validated
  • ☑ Use form.validate() as a means of forcing a full clean with the form's current data (always populated by onChange)
  • FormSet & FormSet-related changes
    • ☑ Add formset.validate([form])
    • ☑ Add formset.addError(error) for adding cross-form errors externally
    • ☑ Add formset.deleteForm(index)
    • ☑ Add form.notEmpty()
      • ☑ Cache the result of hasChanged() each time it's executed
      • Indicates that emptyPermitted no longer applies - use for highlighting required fields in extra forms in FormSets once the user has made a change.
    • ☑ Make addAnother() and deleteForm() call back to re-render when onChange() is available
  • ☑ Allow cross-form validation method to specify which fields it uses (to avoid calling it when possible)
    • API: clean: ['field1', 'field2', function() { ... }]

    • ☑ Detect this in DeclarativeFieldsMeta and transform to equivalent of:

      var clean = function() { ... }
      clean.fields = {'field1': true, 'field2': true}

0.10 (development version)

  • ☑ Remove onStateChange
  • ☑ Fix for using this.addError() in clean() - now checks for duplicates.
  • How can we avoid clearing async validation messages unnecessarily?
    • ☑ Only validate if data has changed since the last validation was triggered.
  • Special cases for onBlur:
    • ☑ Trigger any pending validation.
    • ☑ Always validate if the field is required and empty.
  • ☑ New conditional CSS class Form properties: optionalCssClass & pendingCssClass
  • Async validation
    • API (allow fields to have custom but separate sync and async validation):
      • form.clean<Field>: function([cb]) { } - use existing method, callback optional
      • form.clean: function(cb) { } - use existing method, callback optional
      • formset.clean: function(cb) { } - use existing method, callback optional
      • ☐ Async version of any top-level API which triggers the equivalent of full-form/onSubmit validation.
        • TBD
    • ☑ Async onChange (hooked up automatically by newforms)
      • Custom field validation functions now get a callback if they have an arity of 1
    • Async onSubmit (user's responsibility to hook up)
      • ☐ Callback once all async validation completes
    • ☑ New form state for pending validations
      • ☑ These need to be cancellable for cases where multiple async validations are running simultaneously and some of their results need to be ignored
      • Can be used to display "working" status to the user and to delay final callback for full-form validation until al async validations are complete.
        • ☑ Add a method to BoundField to retrieve this status per-field
          • ☑ Use this to implement display of pending async field validation in default rendering methods.
          • ☐ Add pendingCssClass and generate it from BoundField
        • ☐ Add a method to BaseForm to retrieve pending status for all fields
          • ☐ A Form should never be isComplete() or isValid() if still pending async validation
        • ☐ Add a method to BaseForm to retrieve this status for cross-field validation
          • ☐ Implement display of pending cross-field/whole-form validation in default rendering methods.

Feature Grab-Bag

Everywhere

Improve default rendering

  • Make asDiv() the default and make the existing CSS class configuration more prominent in the docs.
  • Errors appearing above the fields and pushing them down in asTable() is horrible default UX!

Integration between React components and Widgets - e.g. make a CharField use a Widget which renders a component which can mask input based on a format passed to the Field.

  • Add a BoundField method which returns the attributes it would have passed to the widget for use with JSX spread operator

Create a React component for default rendering?

  • Having each Form and Field render via component could also offer better default performance out of the box.

Come up with a better/more intuitive name for BoundField - its name was never day-to-day API in Django due to Python having an iteration protocol and . vs [].

Documentation

  • Split guide sections up into client/server pages
  • Retain most of the existing docs as the server pages - they're focussed on usage of isValid() etc. and use examples which are equivalent to POST data.
  • Extract and rewrite client docs into client pages, with a focus on interactive validation and typical use cases around it, as it's going to be the default mode of operation. No POST-like data examples!

Create a "Field" which wraps a FormSet, allowing you to manage a list of items with a Form.

Disabled/hidden fields

  • Add Field properties for hiding a field entirely or rendering its widget as disabled.
  • Validation/cleaning should skip over disabled/hidden fields
  • Pro: Enables future dynamic use of these, as fields are always present rather than being added or deleted in the constructor
    • Removes the need to construct a new form instance for dynamic fields in correct order.

Client

Break everything up into individual modules

  • Distribute npm version as flattened modules - people who want to save on dependency file size can directly import only what they need.

FileFields need an overhaul on the client side - there are a growing number of Widget.prototype flags which could potentially be used by custom Widgets, but in the core library are only there for special handling of FileFields.

  • See https://github.com/insin/newforms/wiki/Client-side-FileField-Enhancements
  • Need to get a better picture of what typical file input usage is in React apps - I doubt many people will be using them in s submitted via POST, but that's the original use case this API was designed around.
  • Resetting file inputs - can't change the value (in all browsers) due to security restrictions!
    • Keep a number somewhere which is used only in file input key attrs and increment it when an attempt is made to update a file input, to force React to recreate it?
      • form.fields is effectively part of Form instance state, as it's deep-cloned from form.baseFields - could add an own property to FileField for this.
      • After prototyping, may need to introduce (more) special case API: Field.prototype.renderKwargs()

Is there a common approach that could be used to tweak particular field or widget properties on the fly?

  • Dynamic hidden/disabled fields
  • Dynamic field choices
  • These would be reacting to a change in...?
    • initial/data
    • cleanedData
    • any additional state the user needs to pass in
      • Example: Showing/hiding form fields based on external controls/state.

Add support for populating data onChange without providing a containing <form>.

Server

Get usage in String template engines working again

  • toString() methods which are only included in a specific build and call Reaact.renderComponentToString, wrapping with React.createClass as neccessary?
  • Stick with server/browser flag or move to separate builds, source never directly used?
  • Version solely for use with server-side string-based templates? Created an html branch which avoids direct references to React.DOM

Bonus

Theoretically, it should be easy to persist form state should the user refresh or accidentally navigate away - put form.data in localStorage in the onStateChange callback, pass it as initial if present when creating initial component state, clear it after successfully using form.cleanedData.

  • Investigate and document - any helpers which could be provided?

Externalise mutable form state - a form/formset should provide a reference to an object to be set in a component's state.

  • Changes to properties within this object by the form/formset should use React.addons.update().
  • Form would need to be passed a callback which calls setState() for all data/error changes.
  • This would allow easier creation of form-wrapping components which can skip rendering if nothing has changed.
  • For FormSets, with this in place can we create a single form instance and reuse it, tweaking a variable indicating a virtual index within the set? We just then need to keep lists of cleanedData and errors which are actually held independently of the workhorse instance.
Clone this wiki locally