Add new forms to Django form sets dynamically. Supports nested formsets and Bootstrap tabs.
A simple formset
The plugin doesn't automatically add an "add another form" button. You have to do that yourself
somewhere and hook it up to call the
addForm method on the object returned by
Pass a jQuery selection of the form elements in your formset. One of the form elements must be a
form template, and it must have the CSS class passed as option
by default). That class should be styled to be invisible. The correct form prefix is derived from
the name of the first form element in the form template. For every form a Form object is created. If
a form includes a delete checkbox it is replaced with a delete button. Dynamically added forms
always have a delete button. The form object is also accessible via
the any of the form elements.
When a form is added the template is copied and its
empty-form CSS class is removed. The new form
is always added after the last existing form, or after the form template, if there are no existing
forms. Inside the new form in the attributes of the following elements the correct form index is
put in place of
idattribute of the form's root element if that's a
After adding the
formAdded event is triggered to which you can attach a listener to do additional
setup on the new form. The listener is passed the newly created form object. The
elem member of
the form object is the jquery object that contains the DOM node of the new form.
When a form is deleted that was dynamically added before, it is removed from the DOM completely and the remaining forms are renumbered. If a form is deleted that existed on page load, it is just hidden and marked as deleted.
delete() on the form object or
on the object returned by
index is the 0-based form number. Hidden forms count
towards this index as well.
A Bootstrap2-tabbed formset
The tab functionality is triggered by the template form having the CSS class
To find the tab navigation
djangoFormset then looks for a child of a
.nav that has an
<a> or a
<button> with a
data-target that references the
id of the form template root
element. In the example that
id is the form prefix.
When a new form is added a new tab is added after the last visible tab or after the template tab if
there's no visible tab. Inside the tab the
data-target attributes of
<button> elements are updated to reflect the new form index.
When a form is deleted the tab is hidden or removed depending on whether the form existed at page load time or not.
A nested Bootstrap2-tabbed formset
Use the python package django-nested-formset for the Django side of things.
In the view:
formset_class = nestedformset_factory( models.Block, models.Building, nested_formset=inlineformset_factory(models.Building, models.Tenant), )
The plugin takes care to replace just the first occurrence of the template marker
also is careful not to leave the boundaries of the current form instance when it applies the needed
modifications to the DOM. Lastly it provides events to hook up the initialization of the inner
I haven't tried it, but more than one nesting level should work just fine.
- Make examples available at github.com/mbertheau/jquery.django-formset-example
- Handle the delete input being inside its own label (#4)
- Add option
deleteButtonTextto change the text from the default "Delete"
- Add method
Form.field(name)to get a form field by its non-prefixed name
- Add method
Form.prev()to get the previous non-deleted form