{% extends "base.html" %} {% load static sekizai_tags tutorial_tags %} {% block addtoblock %} {{ block.super }} {% addtoblock "js" %}{% endaddtoblock %} {% add_data "ng-requires" "djng.forms" %} {% addtoblock "ng-config" %}['$httpProvider', function($httpProvider) { $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; $httpProvider.defaults.headers.common['X-CSRFToken'] = '{{ csrf_token }}'; }]{% endaddtoblock %} {% endblock %} {% block main-content %} {% block main-intro %}

Django's Forms Set

New in 2.0 How to validate a Set of Forms

This example shows how to validate multiple Forms inside an AngularJS application.

{% endblock main-intro %}
Subscribe Form {{ subscribe_form.as_div }}
Address Form {{ address_form.as_div }}
{% verbatim %}
djng-forms-set's scope:
subscribe_data = {{ subscribe_data | json }}
address_data = {{ address_data | json }}
{% endverbatim %}

How does it work?

{% block main-tutorial %}

In component based web development, it is quite common to arrange more than one form on the same page. As opposed to form submissions via application/x-www-form-urlencoded or multipart/form-data, we can, thanks to Ajax, submit the content of more than one form using a single HTTP-request. This requires to dispatch the submitted data on the server to each form class, but if we prefix them with unique identifiers (using scope_prefix), that's a no-brainer.

Directive djng-forms-set

To achieve this, we can reuse the same Form mixin classes as we have used in the previous examples. The main difference is that we must wrap the set of forms into the AngularJS directive, <djng-forms-set endpoint="/some/endpoint">...</djng-forms-set>. Inside this directive, we render the forms as usual, using {⁠{ form.as_div }⁠}.

Forms Submission

The submit button(s) now can be placed outside of the <form>...</form> element. This allows us to submit the content from multiple forms altogether. However, we must specify the common endpoint to accept our form submissions; this is, as you might have expected, the attribute endpoint="/some/endpoint" in our forms wrapping directive. To send the form's content to the server, add ng-click="do(update())" to the submission button. We have to start this expression with do(...), in order to emulate the first promise (see below for a longer explanation).

By itself, this however would not invoke any further action on the client. We therefore must tell our directive, what we want to do next. For this, the django-angular's button directive offers a few prepared targets, which can be chained. If we change the above to ng-click="do(update()).then(reloadPage())", then after a successful submission the current page is reloaded.

For further options on how to chain actions, please refer to the previous chapter.

Forms Validation

All forms wrapped inside our djng-forms-set directive, are validated. This shall be used to prevent submitting data, if at least one of the forms does not validate. For this, just add ng-disabled="isDisabled()" to the submission button.

{% endblock main-tutorial %} {% block main-sample-code %} {% autoescape off %}
{% pygments "forms/forms_set.py" %}
{% pygments "views/forms_set.py" %}
{% pygments "tutorial/forms-set.html" %}
{% endautoescape %} {% endblock main-sample-code %}
{% endblock main-content %}