jQuery Django Dynamic Formset Plugin
JavaScript CSS Python
Switch branches/tags
Failed to load latest commit information.
.travis.yml Remove travis support for node 0.8 Apr 15, 2014
CONTRIBUTING.md initial commit; v1.0.0 Oct 14, 2013
bower.json Bump version to 1.0.4. Jun 13, 2014
django-superformset.jquery.json Bump version to 1.0.4. Jun 13, 2014
package.json Update grunt plugins. Apr 14, 2014


Django Superformset

Build Status Built with Grunt

jQuery Django Dynamic Formset Plugin

Getting Started

Download the production version or the development version.

In your web page:

  <fieldset class="formlist">
    <input id="form-TOTAL_FORMS" type="hidden" value="1">
    <input id="form-MAX_NUM_FORMS" type="hidden" value="3">
    <div class="dynamic-form">
      <input type="checkbox" class="remove-row" name="form-0-DELETE" />
      <input type="checkbox" name="form-0-input" />
      <!-- any other inputs... -->
  <div class="empty-form">
    <div class="dynamic-form" data-empty-permitted="true">
      <input type="checkbox" class="remove-row" name="form-__prefix__-DELETE" />
      <input type="checkbox" name="form-__prefix__-input" />
      <!-- any other inputs... -->

<script src="jquery.js"></script>
<script src="dist/django-superformset.min.js"></script>

jQuery(function($) {


There are numerous options documented in the development version.

Available options, explictly set to their defaults:

    prefix: 'form',                 // The form prefix for your django formset
    containerSel: 'form',           // Container selector (must contain rows and formTemplate)
    rowSel: '.dynamic-form',        // Selector used to match each form (row) in a formset
    formTemplate: '.empty-form .dynamic-form',
                                    // Selector for empty form (row) template to be cloned to
                                    // ...generate new form instances
                                    // ...This must be outside the element on which ``formset`` is
                                    // ...called, but within the containerSel
    deleteTrigger: '<a href="#" class="remove-row" title="remove">remove</a>',
                                    // The HTML "remove" link added to the end of each form-row
                                    // ...(if ``canDelete: true``)
    deleteTriggerSel: '.remove-row',// Selector for HTML "remove" links
                                    // ...Used to target existing delete-trigger, or to target
                                    // ...``deleteTrigger``
    addTrigger: '<a href="#" class="add-row" title="add">add</a>',
                                    // The HTML "add" link added to the end of all forms if no
                                    // ...``addTriggerSel``
    addTriggerSel: null,            // Selector for trigger to add a new row, if already in markup
                                    // ...Used to target existing trigger; if provided,
                                    // ...``addTrigger`` will be ignored
    addedCallback: null,            // Function called each time a new form row is added
    removedCallback: null,          // Function called each time a form row is deleted
    deletedRowClass: 'deleted',     // Added to deleted row if ``canDelete: false``
    addAnimationSpeed: 'normal',    // Speed (ms) to animate adding rows
                                    // ...If false, new rows will appear without animation
    removeAnimationSpeed: 'fast',   // Speed (ms) to animate removing rows
                                    // ...If false, new rows will disappear without animation
    autoAdd: false,                 // If true, the "add" link will be removed, and a row will be
                                    // ...automatically added when text is entered in the final
                                    // ...textarea of the last row
    alwaysShowExtra: false,         // If true, an extra (empty) row will always be displayed
                                    // ...(requires ``autoAdd: true``)
    deleteOnlyActive: false,        // If true, extra empty rows cannot be removed until they
                                    // ...acquire focus (requires ``alwaysShowExtra: true``)
    canDelete: false,               // If false, rows cannot be deleted (removed from the DOM).
                                    // ...``deleteTriggerSel`` will remove ``required`` attr from
                                    // ...fields within a "deleted" row
                                    // ...deleted rows should be hidden via CSS
    deleteOnlyNew: false,           // If true, only newly-added rows can be deleted
                                    // ...(requires ``canDelete: true``)
    insertAbove: false,             // If true, ``insertAboveTrigger`` will be added to the end of
                                    // ...each form-row
    insertAboveTrigger: '<a href="#" class="insert-row" title="insert">insert</a>',
                                    // The HTML "insert" link add to the end of each form-row
                                    // ...(requires ``insertAbove: true``)
    optionalIfEmpty: true,          // If true, required fields in a row will be optional until
                                    // ...changed from their initial values
    optionalIfEmptySel: '[data-empty-permitted="true"]'
                                    // Selector for rows to apply optionalIfEmpty logic
                                    // ...(requires ``optionalIfEmpty: true``)

Release History

  • 1.0.4 - (06/13/2014) Bugfix: Allow adding row after deleting all rows with canDelete: true
  • 1.0.3 - (04/16/2014) Make totalForms and maxForms selectors less restrictive
  • 1.0.2 - (02/20/2014) Add deletedRowClass option
  • 1.0.1 - (02/19/2014) Add bower.json
  • 1.0.0 - (10/14/2013) Initial release