{% extends "subscribe-form.html" %} {% load static sekizai_tags djng_tags tutorial_tags %} {% block addtoblock %} {{ block.super }} {% addtoblock "ng-config" %}['$httpProvider', function($httpProvider) { $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; $httpProvider.defaults.headers.common['X-CSRFToken'] = '{{ csrf_token }}'; }]{% endaddtoblock %} {% endblock addtoblock %} {% block main-intro %}
Django Form's two-way data-binding with an AngularJS controller
New in version 2.0 This example shows how to reflect Django's form data into an AngularJS controller.
{% endblock main-intro %} {% block form_tag %}name="{{ form.form_name }}" method="post" action="." djng-endpoint="." ng-model-options="{allowInvalid: true}" novalidate{% endblock %} {% block form_submission %} {% endblock %} {% block form_foot %} {% verbatim %}subscribe_data = {{ subscribe_data | json }}{% endverbatim %} {% endblock form_foot %} {% block main-tutorial %}
When working with Django Forms and AngularJS, it is a common use case to upload the form's model
data to an endpoint on the server. If the directive ng-model
is added to an input
field, then, thanks to AngularJS's two-way databinding, the scope
object contains a
copy of the actual input field's content.
ng-model
to formsIf a form inherits from the mixin class NgModelFormMixin
, then
django-angular renders each field with the directive
ng-model="fieldname"
scope_prefix
. Furthermore, set the class member form_name
to a different name. If omitted, the mixin class will invent a unique form name for you. The
form_name
must be different from scope_prefix
, because
AngularJS's internal form controller adds its own object to the scope, and this objects is
named after the form. To prevent confusion, name your forms ending in something such as
…_form
…_data
In this example, an additional server-side validations has been added to the form: The method
clean()
rejects the combination of “John” and “Doe” for the first- and last name
respectively. Errors for a failed form validation are send back to the client and displayed on top
of the form.
djng-endpoint
We must inform the client where we want the form data to be sent. For this purpose,
django-angular offers the attribute directive
<form djng-endpoint="/path/to/endpoint">
action="…"
Form data submitted by Ajax, is validated by the server using the same functionality as if it
would have been submitted using the classic application/x-www-form-urlencoded
{"formname": {"errors": {"fieldname1": ["This field is required."]},
"__all__": ["The combination of username and password is not correct."]}}}
. Just as
in Django, the __all__
is used for form errors not associated with a certain field.
Such an error, typically is rendered on top of the form.
Sometimes it is desirable to use an Ajax request to prefill all or a subset of the form fields with
values. Whenever the Django endpoint adds an object such as {"formname": {"models":
{"fieldname1": "Some value", "fieldname2": "Other value"}}}
to the response object,
then the django-angular form-controller adds those values to the form's input
fields.
The submit button(s) must be placed anywhere inside the <form>…</form>
element. To send the form's content to the server, add ng-click="do(update())"
do(…)
, in order to
emulate the first promise, see below.
By itself, do(update())
would just send the data to the server, but not invoke any
further action on the client. We therefore must tell our directive, what we want to do next. For
this purpose, django-angular's button directive offers a few prepared targets,
which all can be chained in any order. If we change the above to
ng-click="do(update()).then(reloadPage())"
Note: The AngularJS app is configured inside Django's HTML
template code, since template tags, such as {{ csrf_token }}
can't be
expanded in pure JavaScript.