Skip to content
insin edited this page Nov 20, 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 versions of any top-level API which triggers the equivalent of full-form/onSubmit validation.
        • form.validate(cb)
        • Others 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() 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

Client

Does form.addError() need to remove the corresponding field from cleanedData?

  • When used in clean() to mark a particular field as invalid, the field's cleanedData must have been valid up to that point. It forces the user to go back to the field. Scenario: password and confirm. When they don't match use clean() to show the error message on confirm. Now if the user edits password to match confirm, validation won't work, as there's no cleanedData for confirm.

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