Reputation: 1339
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:
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.
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.
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?
Upvotes: 6
Views: 221
Reputation: 29967
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.
Upvotes: 1
Reputation: 154
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.
Upvotes: 0