Handling modal windows in Django - javascript

I use the following approach for handling modal window: check article here https://dmorgan.info/posts/django-views-bootstrap-modals/
But I don't understand how to implement some trivial functionality using such approach
Inside my html I have such thing:
{% for order in queryset%}
<tr>
** some order data here **
<td></td>
<div class="text-center">
<input type="hidden"/>
<a
id="make-offer-button"
role="button"
title="Make offer"
class="btn btn-inverse" data-toggle="modal">
<i class="icon-plus"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
When I click to make-offer-button modal window must appear with particular object. But modal window loads only for the first record in the table, it doesn't work for the second, third, etc., records.
Also I have a great doubt, that modal window has any relation to particular object.
How can I relate particular object with modal window?
JS:
var formAjaxSubmit = function(form, modal) {
$(form).submit(function (e) {
e.preventDefault();
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize(),
success: function (xhr, ajaxOptions, thrownError) {
if ( $(xhr).find('.has-error').length > 0 ) {
$(modal).find('.modal-body').html(xhr);
formAjaxSubmit(form, modal);
} else {
$(modal).modal('toggle');
window.location.replace('http://127.0.0.1:8000/my_orders/');
}
},
error: function (xhr, ajaxOptions, thrownError) {
}
});
});
}
$('#create-order-button').click(function() {
$('#form-modal-body').load('add_order_form/', function () {
$('#form-modal').modal('toggle');
formAjaxSubmit('#form-modal-body form', '#form-modal');
});
});
$('#make-offer-button').click(function() {
$('#form-modal-body').load('make_offer_form/', function () {
$('#form-modal').modal('toggle');
formAjaxSubmit('#form-modal-body form', '#form-modal');
});
});
views.py
class AjaxTemplateMixin(object):
def dispatch(self, request, *args, **kwargs):
if not hasattr(self, 'ajax_template_name'):
split = self.template_name.split('.html')
split[-1] = '_inner'
split.append('.html')
self.ajax_template_name = ''.join(split)
if request.is_ajax():
self.template_name = self.ajax_template_name
return super(AjaxTemplateMixin, self).dispatch(request, *args, **kwargs)
class MakeOfferView(SuccessMessageMixin, AjaxTemplateMixin, FormView, CreateView):
model = ExchangeTransaction
template_name = 'make_offer_form.html'
form_class = ExchangeTransactionForm
success_url = reverse_lazy('all_orders')
success_message = "Way to go!"
def form_valid(self, form):
transaction = form.save(commit=False)
transaction.user = self.request.user
transaction.order = form.order
transaction.save()
return redirect('currency_exchange.views.all_orders')

HTML id attributes must be unique; you have used the same value for each button. Use a class instead.

In the for loop, you are creating the <a> fields with same id (same id's are not allowed). Use class instead, and add action listener to the class.
For your next query, suppose you have a modal code written, and you want it to have different attributes for different objects/items in your html. Handle it using javascript. For a click event on your current object, get the properties of your clicked object, and set it to corresponding attributes in your modal.

When I make modals in a loop, I append the object's id (or something unique to the object) to the button's data-toggle and the modal's id.
For example, your button's data-toggle:
{% for order in queryset%}
...
<a class="btn btn-inverse" data-toggle="modal-{{ order.id }}">
...
{% endfor %}
Then be sure to do the same for your modal:
<div class="modal" id="modal-{{ order.id }}">
...
</div>

Related

Update single row of table in template page using ajax in Django

I am working on Django project and I have no idea of ajax that how to implement it. The scenario is my db contains a table name "demo" which contains the column stat_id. My database contains the following details:
table name = demo
id int primary key NOT NULL,
stat_id int(11) NOT NULL #value is 1
Now, the scenario is that I am getting the stat_id value from database and its purpose to show the running and complete button. If python script is running then it will display the running button and if python script has executed it will display the completed button.
status.html:
<td>
<form action = "/modules" method="get">
{% if status == 1 %}
{% csrf_token %}
<button link="submit" class="btn btn-default btn-sm">
<span class="badge badge-dot mr-4">
<i class="bg-success"></i>Completed</button>
</form>
{% else %}
<button type="button" class="btn btn-default btn-sm">
<span class="badge badge-dot mr-4">
<i class="bg-warning"></i>Running</button>
{% endif %}
views.py:
def process(request):
hash_id = request.session.get('hash_id')
print(hash_id)
check = request.session.pop('check_status',)
if hash_id and check:
stat = status_mod.objects.filter(hash_id = hash_id).order_by('-id').first()
if stat:
stat = stat.stat_id
print(stat)
return render(request, 'enroll/status.html', {'status': stat})
urls.py:
path('status', views.process, name='process')
models.py:
class status_mod(models.Model):
id = models.BigIntegerField(primary_key=True)
stat_id = models.BigIntegerField()
class Meta:
db_table = "demo"
jquery / ajax in my status.html page:
<script>
$(document).ready(function() {
setInterval(function() {
$.ajax({
type: 'GET',
url: "{% url 'process' %}",
success: function(response){
console.log(response)
},
error: function(response){
alert("NO DATA FOUND")
}
});
}, 2500);
});
</script>
Now, I want to update my table row as situation will be if status == 1 then completed button will display else running. Hence it is working fine without ajax but I have to refresh again and again when process function is executed. So, I want to use ajax in this case to update the table row automatically without reloading it.

Send items from forloop populated data in django template through ajax to django view

I have been trying to create a click and populate div with ajax in my django e-commerce application. The project works in such a way that when a customer clicks on a category in men's page it populates another div
gender.html
{%for cate in cat%}
<a href="javascript:getcat()" id="catgend" cats-data="{{cate.catname}}" gen-data="{{gens.gender}}" data-sort-url="{% url 'Home:sortcat' cpk=cate.pk %}" >{{cate.catname}}</a>
{% endfor %}
<div id="products">
<div class="progress">
<img src="{% static 'img/load.gif'%}">
</div>
</div>
This sends the data to my django view through the ajax function called getcat but the data sent through is that of the first item in the loop in-respective of the loop item clicked on. below is my ajax function:
getcat()
function getcat() {
$(".progress").show()
var cat = $("#catgend").attr("cats-data");
var gender = $("#catgend").attr("gen-data");
var url = $("#catgend").attr("data-sort-url");
$.ajax({
url: url,
data: {
'cat': cat,
'gender': gender,
},
success: function (data) {
$("#products").html(data);
}
});
$(".progress").hide()
}
enter code here
From my research i discovered its because they have same ID. How do i solve the issue of dynamically changing the id over the same loop. Thanks
Replace the id attribute with a class attribute since you shouldn't have more than a single element with the same id. Also, we can change cats-data and gen-data to valid data-* attributes.
{% for cate in cat %}
<a href="#" class="catgend" data-cats="{{cate.catname}}" data-gen="{{gens.gender}}" data-sort-url="{% url 'Home:sortcat' cpk=cate.pk %}" >{{cate.catname}}</a>
{% endfor %}
Bind a click event to anchors using the new class name.
$('.catgend').on('click', function (e) {
$('.progress').show()
var data = $(this).data()
$.ajax({
url: data.sortUrl,
data: {
'cat': data.cats,
'gender': data.gen,
},
success: function (data) {
$('#products').html(data);
}
});
$('.progress').hide()
});
Utilise the data attributes to accumulate data values in a simple way.

Django jquery AJAX form submission in view and display results

There are a lot of different posts about all parts of this, I just can't quite figure out how it all fits together.
I have name that is displayed with an update button next to it. When the update button is clicked it shows a form to update the name. In the form is a save changes button. When the changes are saved, it should reload the name at the top, and should the update button be clicked again, the form should show the new name info.
urls.py
path('profile/<int:pk>/', views.customer_profile, name='profile'),
path('update-profile/<int:pk>/', views.update_profile, name='update-profile'),
views.py
def customer_profile(request, pk):
name = get_object_or_404(CEName, id=pk)
name_form = NameForm(instance=name)
return render(
request,
'customer/customer_profile.html',
{'name':name, 'NameForm': name_form}
)
def update_profile(request, pk):
if request.POST:
name_form = NameForm(request.POST)
if name_form.is_valid():
name_form.save()
name = get_object_or_404(CEName, id=pk)
context = {'name':name, 'NameForm': name_form}
html = render_to_string('customer/customer_profile.html', context)
return HttpResponse(html, content_type="application/json")
template.html
<div id="name" class="container d-flex justify-content-between pt-1">
{{ name }}
<button id="update_button" class="bold btn btn-main btn-sm button-main">UPDATE</button>
</div>
<div id="div_NameForm" class="container" style="display: none;">
<hr size="3px">
<form id="NameForm" method="POST" data-url-name="{% url 'customer:update-profile' name.id %}">
{% csrf_token %}
{{ NameForm.as_p }}
<br>
<button type="submit" id="save_changes" class="btn btn-main button-main btn-block">Save Changes</button>
</form>
</div>
<script src="{% static 'ce_profiles/ce_profiles_jquery.js' %}"></script>
jquery.js
$('#save_changes').click(function() {
var NameForm = $('#NameForm');
$.ajax({
type: 'post',
url: NameForm.attr('data-url-name'),
data: NameForm.serialize(),
dataType: 'json',
success: function(data, textStatus, jqXHR) {
$('#name').html(data);
}
});
});
The code for the update button toggle is not displayed.
In your jQuery, to start with.
- First, you could (some may say should) have put a submit event handler on the on the form instead of a click event for button.
- Second, you are doing an AJAX call so you should prevent form submission using .preventDefault() on the submit event that was trigged when the button was pressed. This will prevent the page from reloading.
- Third, in your ajax success callback you should use text() instead of html() since name I imagine is text and not html, however that's just an assumption.
$('#NameForm').on('submit', function(evt) {
evt.preventDefault();
var NameForm = $('#NameForm');
$.ajax({
...
success: function(response) {
$(#name).text(response); // or response.name or whatever
}
});
})

How to refresh a part of the DOM HTML when querying a foreign django view

Hello Awesome People!
So many questions on StackOverflow are about "How to refresh dom via jquery (from the same view/url)" It's not what I'm looking for.
With a website that large of its parts are running with ajax, I wonder how to refresh a part of the HTML DOM when querying a foreign django view.
Let me be clearer with some examples:
I have that view that sends all_users to template
def usersList(request):
all_users = User.objects.all()
return render(request,'administration/users-list.html',{'all_users':all_users})
In the template I loop through all_users... The 2nd <span> reflects the activation state of the user
{% for u in all_users %}
<span>{{forloop.counter}}.- {{u.name}} <span>
<span id='user_{{u.id}}_state'>
<button data-id='{{u.id}}' type='button' class='css-btn btn-circle'>
{% if u.is_activate %} Active{% else %}Inactive{% endif %}
</button>
<span>
{% endfor %}
With jquery, I send a request to a specific view responsible only to activate or deactivate the account of the user. We can activate/deactivate user in many parts of the website, that's why I do so in a different view.
Here's the view:
def deactivateUser(request):
user = request.user
if user.has_perm('is_admin') and request.is_ajax() and request.method == 'POST':
id_user = request.POST.get('id')
targeted_user = get_object_or_deny(User,id=id_user)
# get_object_or_deny is my own function
it will get the object or raise PermissionDenied otherwise
if targeted_user.is_activate:
targeted_user.is_activate = False
state = 'deactivated'
else:
targeted_user.is_activate = True
state = 'activated'
targeted_user.date_update_activation = NOW() # own function
targeted_user.save()
return JsonResponse({'done':True,'msg':'User successfully %s' %s state})
# Here we return a JsonResponse
raise PermissionDenied
So now, how can I refresh the Dom with following jquery stuff to get the current state of each user
$(document).on('click','.btn-circle',function(){
var id = $(this).data("id");
$.ajax({
url:'/u/de-activate/?ref={{ request.path }}',
type:'post',
data:{
csrfmiddlewaretoken:"{{ csrf_token }}",
id:id,
},
success:function(response){
$("#user_"+id+"_state").replaceWith($("#user_"+id+"_state",response));
if(response.created) alert(response.msg);
},
error:function(){
alert("An error has occured, try again later");
}
});
});
Note that all_users is required to loop through. deactivateUser() return a Json response, even though it doesn't returned it, it will not matter.
You can send http response, not json.
First, just move your html that want to change. in this situation,
{% for u in all_users %}
<div id="user-part">
<span>{{forloop.counter}}.- {{u.name}} <span>
<span id='user_{{u.id}}_state'>
<button data-id='{{u.id}}' type='button' class='css-btn btn-circle'>
{% if u.is_activate %} Active{% else %}Inactive{% endif %}
</button>
<span>
</div>
{% endfor %}
Then save it i.e. user_part.html
Second, make your view return HttpResponse with that html, and context. You can use either HttpResponse or render_to_response. I recommend render_to_response.
context = {
'all_users': all_users,
}
return render_to_response(
'path_to/user_part.html',
context=context,
)
Third, you just change script for replacing your html.
success: function(response){
$('#user-part').html(response);
prevent();
}

Django, jQuery. I can't load() after the same div multiple times

I am trying to let the user create multiple types of the same input form.
The problem is that the first time I click on the button a form is appended to the append_form div, but no matter how many more times I click on the "Add" button, no other form is appended. What am I doing wrong?
This is my HTML code:
<div class="col-md-9"><strong>{% trans "Please, add as many measures as you like to be available for the institutional simulation" %}</strong></div>
<div class="col-md-3"><button class="btn btn-success" onclick="addForm('{% url "add_measure_form" %}')"><i class="fa fa-plus-square"></i> {% trans "Add Measure" %} </button></div>
<div id="append_forms"></div>
And this is my script
function addForm(url){
$("#append_forms").after().load(url);
}
And this is my django views:
def add_measure_form(request):
data = {
}
return render(request, "_frm_inner_form.html", data)
and urls
url(r'^measures/form/add/$', add_measure_form, name="add_measure_form")
remove the after() function append a wrapper div to the forms and load the data into it:
function addForm(url){
$("#append_forms").append('<div>').load(url);
}
or use the general ajax request
$.ajax({
url:url,
success:function(data) {
$("#append_forms").append(data);
}
});

Categories

Resources