jquery ajax / django - 呈现形式的引导模态并重新显示,如果验证不成功 [英] jquery ajax / django - present form in a bootstrap modal and re-show if validation was not successfull

查看:214
本文介绍了jquery ajax / django - 呈现形式的引导模态并重新显示,如果验证不成功的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的用例是:

a)呈现一个通过ajax加载的引导模式,花式叠加效果东西.. 。我遵循了这些说明

a) Present a form loaded via ajax in a bootstrap modal, the fancy overlay effect stuff.. . I followed these instructions.

这工作正常。 (见下面的代码)

This works fine. (see code below)

b)将此表单提交回我的Django应用程序,尝试验证,如果不验证,请重新显示该表单与花哨自举模式中的错误。

b) Submit this form back to my Django app, try to validate it, and if it does not validate, re-show the form with the errors in the fancy bootstrap modal.

我可以通过ajax重新载入表单,但我无法在模态中再次表示。

I can reload the form via ajax, but I m not able to represent it again in the modal.

注意:我没有包含视图,因为它没有什么特别的。只有实例化和验证表单。

Note: I did not include the view since it does nothing special. Only instantiating and validating the form.

下面很多阅读,所以只要继续,如果你认为用例听起来很有趣...

Quite a lot to read below, so just continue if you think the use case sounds interesting...

我的taskList.html如下所示:

My taskList.html looks like this:

<table id="listItemTable" class="table table-bordered">
        <thead>
            <tr>
                <th>Name</th>
                <th>Edit</th>
            </tr>
        </thead>
    <tbody>
        <tr>
            <td>Task 1</td>
            <td><a class="editItem" href="/update/item/1/">edit</a></td>
        </tr>
    </tbody>
</table>

<div class="modal hide" id="itemFormModal"></div>
<div id="modalExtraJsPlaceholder"></div>

.js加载表单+显示引导模态+绑定表单到.jquery提交调用:

.js for loading the form + showing the bootstrap modal + binding form to a .jquery submit call:

$(document).ready(function() {
   modalConnect();
});

<script type="text/javascript">
 //connects the modal load for each <a> with class editItem
 //Functionality 1
     //loads an item edit form from the server and replaces the itemFormModal with the form
     //presents the modal with $("#itemFormModal").modal('show');
 //Functionality 2
     //loads some extra js "modalExtraJsHtml"
     //calls the function "submitItemModalFormBind" which has been loaded via "modalExtraJsHtml"

 function modalConnect(){
    $(".editItem").click(function(ev) { // for each edit item <a>
    ev.preventDefault(); // prevent navigation
    url = ($(this)[0].href); //get the href from <a>
    $.get(url, function(results){
       var itemForm = $("#ajax_form_modal_result", results);
       var modalExtraJs = $("#modalExtraJs", results);
       //get the html content
       var modalExtraJsHtml = modalExtraJs.html();
       //update the dom with the received results
        $('#itemFormModal').html(itemForm);        
        $('#modalExtraJsPlaceholder').html(modalExtraJsHtml);
        $("#itemFormModal").modal('show');
        submitItemModalFormBind(); //bind loaded form to ajax call
     }, "html");
     return false; // prevent the click propagation
   })
}
</script>

从视图返回的itemForm如下所示:

The itemForm returned from the view looks like this:

<form id="#ajax_form_modal_result" class="well" method="post" action="/update/item/{{ item.id }}">
 <div id="ajax_form_modal_result_div">
     <div class="modal-header">
      <button type="button" class="close" data-dismiss="modal">×</button>
      <h3>Edit Item</h3>
    </div>
    <div class="modal-body">
         {% csrf_token %}
         {{form.as_p}}
    </div>
    <div class="modal-footer">
         <input class="btn btn-primary" type="submit" value="Save" />
         <input name="cancel" class="btn" type="submit" value="Cancel"/>
     </div>
    </div>
</form>

加载并显示模态工作正常。
但是现在第二部分没有按预期工作。问题是如下。如果表单不验证,则视图返回表单。返回的表单应该再次显示在引导模式中。但结果是只有窗体在浏览器中显示,其他一切都丢失了。没有css,没有表,只有形式。相当丑陋..所以我没有实现更新ajax_form_modal_result_div。任何人都可以帮助我在这里做错了什么..!?

Loading and showing the modal works fine. But now comes the second part which does not work as expected. The issue is the following. If the form does not validates, the view returns the form. The returned form should be shown again in the bootstrap modal. But the result is that ONLY the form is presented in the browser, everything else is lost. No css, no table, only the form. Quite ugly.. Thus I did not achieve to update the ajax_form_modal_result_div. Can anyone help me out here what I m doing wrong..!?

该视图还返回了js函数submitItemModalFormBind,它阻止了表单默认行为并发送表单通过ajax。

The view returns also the js function 'submitItemModalFormBind' which prevents the form default behavior and sends the form via ajax.

<div id="modalExtraJs">
 //ajax bind for update item form visualized via modal
 function submitItemModalFormBind(){
     var url = "{% url updateItem item.pk %}";
     $('#ajax_form_modal_result').submit(function(){
 $.ajax({
    type: "POST",
    url: "{% url updateTask item.pk %}",
    data: $(this).serialize(),
    success:function(response){
        var div = $("ajax_form_modal_result_div", response);
        $('#ajax_form_modal_result_div').html(div);
     },
     error: function (request, status, error) {
         console.log("failure");
         console.log(request.responseText);
     }

           });
          });
        return false;
       }    
</div> 

感谢任何帮助!

推荐答案

找到一个有效的方法(根据这个解决方案,并通过处理无效表单进行增强),并将其发布给任何想要使用令人惊叹的美丽自举模式与django的人。上面的代码的主要问题是我没有正确禁用提交按钮的默认行为,并且加载其他js的方法不是一个好主意。所以我改变了我的策略。

Found a working approach (based upon this solution - and enhanced it with handling of invalid forms) and will post it for anybody who also want to use the stunning beautiful bootstrap modals with django. Major issue with the code above was that I did not correctly disabled the default behavior of the submit button and the approach for loading additional js was not a good idea. So I changed my strategy.

在documentReady或ajaxStop事件上将超链接的点击事件绑定到modalConnect函数。请注意,如果您有某种更新表的内容(我有)的ajax,则只需要ajaxStop函数:

On documentReady or ajaxStop event bind the click event of the hyperlinks to the modalConnect function. Note that you only need the ajaxStop function if you have some kind of ajax which updates the content of your table (which I have):

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

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

modalConnect函数加载我们要呈现在模态中的表单和一个formUpdateURLDiv: p>

The modalConnect function which loads the form which we want to present in the modal and a formUpdateURLDiv:

<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
                  $('#itemFormModal').html(itemForm);
                  //show the bootstrap modal
                  $("#itemFormModal").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>

formUpdateURL包括生成的服务器(请参阅下面的包含视图)url,加载的表单必须其表单提交调用。我们使用这个url来initsubmitItemModalFormBind函数:

the formUpdateURL includes a server generated (see included view below) url to which the loaded form has to make its form submission call. We use this url to "init" the submitItemModalFormBind function:

<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);
                         $("#itemFormModal").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
                        document.open();
                        document.write(response);
                        document.close();
                        //sort by modified date descending

                        //var notificationDiv = $("#notification", response);
                        //$('#notification').html(notificationDiv.html());
                        console.log('Form was valid and was not returned');
                        $("#itemFormModal").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>

..并查看服务器上发生的事情,请看下图处理逻辑的视图:

..and to see what is going on at the server see below the view which handles the logic:

class UpdateTaskModalView(LoginRequiredMixin, View):
template = 'list_management/crud/item/update_via_modal.html'

def get_logic(self, request, task_id, **kwargs):
    task = get_object_or_404(Task.objects, pk=task_id)
    task_form = TaskForm(instance=task)
    context = {
               'model_form': task_form,
               'item': task,
    }
    return context

def post_logic(self, request, task_id, **kwargs):
    task = get_object_or_404(Task.objects, pk=task_id)
    task_form = TaskForm(request.POST, instance=task)
    if task_form.is_valid():
        task = task_form.save(commit=False)
        task.modified_by = request.user
        task.save()
        messages.add_message(request, messages.INFO, 'Item "%s" successfully updated' % (task.name))
        return ('redirect', HttpResponseRedirect(reverse('show_list_after_item_update', kwargs={'list_id':task.list.pk, 'item_id':task.pk})))
    context = {
        'model_form' : task_form,
        'list': task.list,
        'item': task,
    }
    return ('context', context)

def get(self, request, task_id, **kwargs):
    context = self.get_logic(request, task_id, **kwargs)
    return render_to_response(
        self.template,
        context,
        context_instance = RequestContext(request),
    )

def post(self, request, task_id, **kwargs):
    post_logic_return = self.post_logic(request, task_id, **kwargs)
    if post_logic_return[0] == 'redirect':
        return post_logic_return[1]
    if post_logic_return[0] == 'context':
        context = post_logic_return[1]
        return render_to_response(
            self.template,
            context,
            context_instance = RequestContext(request),
        )

..表单模板已经包含在我的问题中:ajax_form_modal_result_div,你只需要提供formUpdateURL。我通过模板,这似乎很奇怪,我写这篇文章。可以通过视图上下文轻松提供。

..the form template is already included in my question: ajax_form_modal_result_div, you only have to provide also the formUpdateURL. I did it via the template, which seems quite odd now that I write this post. could be easily provided via the view context.

Voila - 具有Bootstrap模式的Django表单!调整你的UI!

Voila - Django Forms with Bootstrap Modals! Spice up your UI!

我希望这有助于某人解决类似的问题。

I hope this helps somebody to solve a similar problem.

这篇关于jquery ajax / django - 呈现形式的引导模态并重新显示,如果验证不成功的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆