Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
236 views
in Technique[技术] by (71.8m points)

javascript - Asynchronous forms with bootstrap and django

So i'm trying to make this form asyncronous. Ideally, I'm using this form to add units, and then update the table dynamically. I do not want the entire page to refresh. I'm not all that good with javascript, and I could use some pointers with what's going on:

A few things are happening that I don't want to happen:

  1. The entire page is refreshing
  2. request.is_ajax() is False.

Mostly, I'm just trying to understand what's going on, but the question is, how do I change the below to fix the above two issues? (if they are issues are issues at all.)

Some of the below code is taken from this question:

How do I insert a django form in twitter bootstrap modal window?

For the record, I am seeing the post just fine in request.POST, I just want to make it work Asyncronously, which is how my question differs from the above.

{% block scripts %}
<script type="text/javascript">
    $(document).ready(function() {
        modalConnect();
    });
</script>

<script type="text/javascript">
$( document ).ajaxStop( function() {
    modalConnect();
});
</script>

<script type="text/javascript">
    function modalConnect()
        {
            //unbind the click event. If not done we will end up with multiple click event bindings, since binding is done after each ajax call.
            $(".editItem").unbind('click');
            //bind the click event
            $(".editItem").click(function(ev) { // for each edit item <a>
                ev.preventDefault(); // prevent navigation
                var url = this.href; //get the href from the <a> element
                $.get(url, function(results){
                  //get the form
                  var itemForm = $("#ajax_form_modal_result", results);
                  //get the update URL
                  var formUpdateURLDiv = $("#formUpdateURL", results);
                  //get the inner html of the div
                  var formUpdateURL = formUpdateURLDiv.html();
                  //update the dom with the received form
                  $('#inventory').html(itemForm);
                  //show the bootstrap modal
                  $("#inventory").modal('show');
                  $(document).ready(function () {
                     //bind the form to an ajax call. ajax call will be set to the received update url
                     submitItemModalFormBind(formUpdateURL);
                  });
                }, "html");
                return false; // prevent the click propagation
            })
        }
</script>

<script type="text/javascript">
       function submitItemModalFormBind(url){
         //bind the form. prevent default behavior and submit form via ajax instead
         $('#ajax_form_modal_result').submit(function(ev){
             $.ajax({
                type: "POST",
                url: url,
                data: $(this).serialize(),
                success:function(response, textStatus, jqXHR){
                     var form = $("#ajax_form_modal_result_div", response);
                     //form is returned if it is not valid. update modal with returned form
                     //change this "if" to check for a specific return code which should be set in the view
                     if (form.html()) {
                        console.log('Form was invalid and was returned');
                        //update modal div
                         $('#ajax_form_modal_result_div').html(form);
                         $("#inventory").modal('show');
                      }
                      //form is not returned if form submission succeeded
                      else{
                        //update the entire document with the response received since we received a entire success page and we want to reload the entire page

                        //sort by modified date descending

                        //var notificationDiv = $("#notification", response);
                        //$('#notification').html(notificationDiv.html());
                        console.log('Form was valid and was not returned');
                        $("#inventory").modal('hide');
                        }
                },
                error: function (request, status, error) {
                            var div = $("ajax_form_modal_result_div", request.responseText);
                            $('#ajax_form_modal_result_div').html(div);
                            //implement proper error handling
                            console.log("failure");
                            console.log(request.responseText);
                        }
                    });
                    return false;
                });
              }
</script>



{% endblock %}

{% block content %}

<div class="row">
    <div class="span8 offset4">
        <div class="row">
            <div class="span3">
                <h1>
                Acquisitions
                </h1>
            </div>
            <div class="span3 offset2">
                <h1>
                <a id="editItem" href="#inventory" role="button" class="icon-plus-sign" data-toggle="modal"></a>
                Add Units
                </h1>
            </div>
        </div>
        <table class="table table-hover table-striped">
            <thead>
                <tr>
                    <th>
                    lolcats
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>
                    lolcats
                    </td>
                </tr>
                    <tr>
                    <td>
                    test
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>


    <div class="modal hide fade" id="inventory" >
<form id="#ajax_form_modal_result" class="well" method="post" action="">
 <div id="ajax_form_modal_result_div">


    <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
    <h3>Add units</h3>
    </div>
    <div class="modal-body">
        {% csrf_token %}
         {{inventory.as_p}}

    </div>
    <div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <input class="btn btn-primary" type="submit" value="Save" />

    </div>

   </div>
</form>
</div>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I struggled horribly with AJAX when I started with Django due to a lack of JS experience.

I will give you an example of an aync form I use to add options and display the options.

My template modal code is as follows, and it will work just as well with the form being rendered rather than my lazy hardcoded html.

   <div class="modal" id="AddOptions" style="display:none;">
  <div class="modal-header">
    <button class="close" data-dismiss="modal">X</button>
    <h3>Add Options</h3>
  </div>
  <div class="modal-body">

<form id="OptionForm" action="." method='POST'>
  <div id="OptionValueError" class="control-group">
  <span class="help-inline"></span><br>
  <br>Value&nbsp;<input type="text" name="OptionValue" id="id_OptionValue" /><br>Label&nbsp;<input type="text" name="OptionLabel" id="id_OptionLabel"/><input type="hidden" name="VariableID">
  </div>
<div id="divid_OptionTable">
<table class="table table-condensed" id="OptionTable">
<thead>
  <th>Value</th>
  <th colspan="2">Label</th>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
  <div class="modal-footer">
  <input type="submit" class="btn btn-primary" value="Add">&nbsp;<button type="reset" class="btn">Reset</button>
</form>
  </div>
</div>

Next, make sure that the following is in your to take care of CSRF token issues.

<script type="text/javascript"> 
jQuery(document).ajaxSend(function(event, xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    function sameOrigin(url) {
        // url could be relative or scheme relative or absolute
        var host = document.location.host; // host + port
        var protocol = document.location.protocol;
        var sr_origin = '//' + host;
        var origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(//|http:|https:).*/.test(url));
    }
    function safeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

    if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});
</script>

Second, this is what a basic AJAX POST would look like using jQuery. Notice it is based on preventing the Default submission behaviour of the form living in our modal. On success I am appending the newly added values to the table. It would be less troublesome to add the values as part of catching the form, but I like to be sure everything has been saved and processed before being added to the table.

   $(document).ready(function() {
   $("#OptionForm").submit(function(event){
       event.preventDefault();
       $.ajax({
            type:"POST",
            url:"{% url builder.views.addoption %}",
            data: {VariableID: $('input:hidden[name=VariableID]').val(), OptionLabel: $('input:text[name=OptionLabel]').val(), OptionValue: $('input:text[name=OptionValue]').val()},
            success: function(data){
            console.log(data['OptionID']);
            $("#OptionValueError").removeClass("error");  
            $("#OptionValueError span").text("");  
            $("#OptionValueError span").removeClass("error");
            $('#OptionTable > tbody:last').append('<tr id=Option_'+data['OptionID']+'><td>'+data['OptionValue']+'</td><td>'+data['OptionLabel']+'</td><td><a href="#" onClick="deleteOption('+data['OptionID']+')"><i class="icon icon-remove"></i></a>');
            $('input:text[name=OptionValue]').val('');
            $('input:text[name=OptionLabel]').val('');
            }
          });
       });
    });

Lastly, you just need the view that captures this AJAX request, which would look like this partially written one below.

def addoption(request):
    if request.is_ajax():
        OptionValue = int(request.POST['OptionValue'])
        OptionLabel = request.POST['OptionLabel']
        VariableID = int(request.POST['VariableID'])
        getVar = Variable.objects.get(id=VariableID)
        newOption = Option(VariableID=getVar,
                Value=OptionValue,
                Label=OptionLabel)
        newOption.save()
        response = {'OptionValue': OptionValue, 'OptionLabel': OptionLabel, 'OptionID': newOption.id}
        json = simplejson.dumps(response)
        return HttpResponse(json, mimetype="text/json")
    else:
        pass

The response dict that we are json serializing is what is fed back as data and subsequently used to append the values to the table. All without reloading the main page.

Hopefully the example helped. Let me know if you have anymore questions.

JD


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...