Tuesday, July 9, 2013

Forms Submit


Django 1.4, JQuery 1.7.2, Bootstrap Twitter
I already talked about how to add forms to pages using Django and now I want to talk about how to prevent double submit of forms.
So, I have following template:
{% block content %}

{% trans "Submit" as submit %}

 <div class="well">
  <h1>{% trans "Report an Issue" %}</h1>
  {% if error_message %}
  <p><strong>{{ error_message }}</strong></p>
  {% endif %}
  <form id="form" enctype="multipart/form-data" method="post" class="form-horizontal">
   <div class="control-group">
    {% csrf_token %}
    {% crispy form %}
    <input type="submit" value="{{ submit }}" class="btn" />
   </div>
  </form>
 </div>

{% endblock %}
It's a usual POST, after submit a user is redirected to another page.
To prevent double submit I will disable submit button on click, to prevent double click from submitting two identical forms, and show a spinner instead of my form. To show a spinner I will add one more div to the template, with loading animtion (gif file) from this nice site http://ajaxload.info/ .
And now my template will look like this:
{% block content %}

{% trans "Submit" as submit %}

 <div class="well">
  <h1>{% trans "Report an Issue" %}</h1>

  {% if error_message %}

  <p>
   <strong>{{ error_message }}</strong>
  </p>

  {% endif %}

  <form id="form" enctype="multipart/form-data" method="post" class="form-horizontal">
   <div class="control-group">
    {% csrf_token %}
    {% crispy form %}
    <input type="submit" value="{{ submit }}" class="btn" />
   </div>
  </form>
 </div>

 <div id="loader" style="display:none;">
  <p><img src="{{ STATIC_URL }}img/loader.gif" />{% trans "Please Wait" %}</p>
 </div>

{% endblock %}
As you can see I add a new div with style set to display:none, so as to not show it before time.
Issue form js file:
$(function(){
 $('input[type=submit]').click(function(){
  $(this).attr('disabled', 'disabled');
  $(this).parents('.well').hide();
  $('#loader').show();
  $(this).parents('#form').submit();
 });
});
Let's take a look at whats going on here. First of all I wait for the document to be ready, which means that the DOM is ready and the content is not rendered yet. I locate my submit button in the DOM and bind handler function to click event. By setting disable attribute to disabled, I prevent double click. I hide the div containing the form, show loader div and submit the form. In my case I don't need to hide the loader after submit and show the form again, because on submit the browser will redirect or re-load the whole page, if the form didn't pass validation.
One more thing, CSS file, without one I got my loader div showing right after nav-bar div, and not centered, so to fix this small problem:
#loader {
 margin-right: 250px;
 margin-top: 150px;
 margin-bottom: 150px;
}
This will show my loader in the middle of the page.
Usually, you don't need to show a spinner in such cases, because the browser will show one, but for the sake of exercise and  those cases when you want to make form submit more pronounced and obvious it is good.


No comments:

Post a Comment