I have a template structure similar to this:
#X_List.html <div class="row"> {% include './X_List_Table.html' %} </div> <div id="confirm" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="testmodal" aria-hidden="true"> <div class="modal-dialog modal-sm" role="document"> <div class="modal-content"></div> </div> </div> #X_List_Table.html <table> <thead> <tr> <th>Desc</th> <th>Activate</th> </tr> </thead> <tbody> {% for item in x_list %} <tr> <td>{{ item.id }}</td> <td><a data-toggle="modal" href="{% url 'x:x_quantity' item.id %}" data-target="#confirm">Click me</a></td> </tr> {% endfor %} </tbody> </table>
My view is defined as:
#views.py def x_quantity(request, id): return render(request, 'modal.html', {'quantity': X.objects.filter(pk=id).count()}
and the modal.html
:
<div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h3>Attention</h3> </div> <div class="modal-body"> <p>The number of elements is {{ quantity }}</p> </div> <div class="modal-footer"></div>
The problem is:
Supposing that I have 2 elements in the table, their urls would be:
'x/x_quantity/1'
'x/x_quantity/2'
Consider that for these elements:
- One returns a QuerySet with atleast 1 element
- One returns an empty QuerySet
When I click on the link, it should run the view, get the quantity
based on the id
of the element, return it as a context variable to the modal so it can be displayed.
The problem is:
When I click on a link, the view is being called with the id
of the element, which can be confirmed by looking at the server shell [06/Apr/2018 17:00:23] "GET /x/x_quantity/1 HTTP/1.1" 200 898
.
If I click on the other element, THE VIEW IS NOT BEING CALLED, there is no request going out.
What I intend to do is to display a modal with the quantity
of the element clicked.
Is this a confusion on my part regarding how the {% url 'app:app_view' var %}
should behave on a href
or I'm not supposed to do this and should, instead, use AJAX?
Perhaps this is related with "refreshing" context variables as well?
2 Answers
Answers 1
The explanation for the behavior you are seeing can be found in the Bootstap documentation:
If a remote URL is provided, content will be loaded one time via jQuery's load method and injected into the .modal-content div. If you're using the data-api, you may alternatively use the href attribute to specify the remote source. An example of this is shown below:
If you want to use the same modal to load different content, you have to use Ajax.
A (quite ugly) workaround would be to render a modal for each item in x_list
. Just be aware that the value doesn't get updated if you open the same modal twice.
Answers 2
Let me first clarify that before this example I have never used Bootstrap. I found your question interesting so I played a little bit with Bootstrap CDN. Also I do not use a lot of Javascript so everyone feel free to correct any bad practices.
I think what you want is doable using AJAX so here is my solution:
I changed a link to a button because all the modal examples had buttons not links :)
#X_List.html <table> <thead> <tr> <th>Desc</th> <th>Activate</th> </tr> </thead> <tbody> {% for x in x_list %} <tr> <td>{{ x.id }}</td> <td><button id="{{ x.id }}" type="button" class="btn btn-info modal-btn">Click me</button></td> </tr> {% endfor %} </tbody> </table> <!-- Modal --> <div id="myModal" class="modal fade" role="dialog"> <div class="modal-dialog"> <!-- Modal content--> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title"></h4> <button type="button" class="close" data-dismiss="modal">× </button> </div> <div class="modal-body"></div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div> </div> </div>
Javascript (you will need js-cookie - I used CDN) passes the id to the server side and then shows received quantity at the end in a modal.
$(document).ready(function() { $(".modal-btn").click(function(event) { var x_id = $(event.target).attr('id'); $.ajax({ url : "/ajaxquantity/", type : "POST", dataType: "json", data : { x_id : x_id, csrfmiddlewaretoken: Cookies.get('csrftoken') }, success : function(json) { var quantity = json.quantity; $(".modal-title").text('Id: ' + x_id); $(".modal-body").text('Quantity: ' + quantity); $('#myModal').modal('show'); }, error : function(xhr,errmsg,err) { alert(xhr.status + ": " + xhr.responseText); } }); return false; }); });
Then you need to add this line into urlpatterns list:
url(r'^ajaxquantity/$', views.ajaxquantity, name='ajaxquantity')
And finally the server side. I do not know how your model looks like so here I used your query from the question.
# views.py def ajaxquantity(request): if "x_id" in request.POST: response_dict = {} x_id = request.POST.get('x_id') quantity = X.objects.filter(pk=id).count() response_dict.update({'quantity': quantity}) return JsonResponse(response_dict) else: return render(request, 'yourapp/X_List.html')
So this worked for me (with a little different QuerySet). It is very important that Jquery is only defined once!!!
Keep in mind that this is a minimal working example.
0 comments:
Post a Comment