node package manager
Don’t reinvent the wheel. Reuse code within your team. Create a free org »


Browser Forms

Constructing a good form by hand is a lot of work. Rails, Django, and jQuery contain code to make this process less painful. This module is an attempt to provide browser-side helpers using the same validators and interfaces caolan/forms to uses for server-side Express form processing.

npm install browser-forms

Heads up! This library is evolving rapidly


Implement polished interaction by default

  • Validation errors appear when the user finishes interacting.
  • Don't show validation errors on an empty form.
  • Don't change invalid input.
  • Disable form submission while processing.
  • Expose hooks to customize interaction where appropriate.

Be flexible with form markup

  • Add a few constraints to keep the API simple.
  • Generate sane default markup.
  • Use your existing templating language and pipeline if you like.
  • Try horizontal or vertical Bootstrap forms.
  • Or vanilla HTML5 inputs.
  • Or jQuery UI widgets.
  • Code against interfaces to allow full custom implementations as needed.

Run on the Server and in the Browser

  • Validators run both places.
  • Use the same interfaces and abstractions to make reuse fun.
  • Don't require a DOM on the server


  • Bootstrap
  • Html5
  • Default Forms
  • Simple tweeks
  • Full custom DOM



  • .value
  • .attach(element)
  • .on('change', callback)
  • .off('change', callback)


  • .attach(attachedWidget, {fieldElement, errorMessageElement, errorClass})
  • .showError(message)
  • .clearError()


  • .attach(element)

DOM Constraints

Build whatever markup you like, but mind these constraints if you want to smooth interactions:

  • Each field must have a root element. It can just be the input, see the HTML5 example.
  • If you're using an errorMessageElement, it should always be in the DOM. Show and hide it with CSS. This gives developers more flexibility in field markup.
  • Each widget must have a root element. Easy for an <input/>, interesting for a radio button group.

Divergence from caolan/forms

  • widget.toHTML() must return a single root element for delegation and location
  • Validators almost exclusively check, why not pass just one arg?