I'm using the sample found here http://stackoverflow.com/questions/27218680/how-can-i-reload-just-one-div-on-click and I think I'm missing something in my example or maybe the value is not passing as I'm using MPTT instead of a standard menu.
This is how I'm loading my menu found in my base.html -
{% recursetree nodes %}
{{ node.name }}
{% endrecursetree %}
Here is the javascript I've included -
<script>
$(document).on('click','.node',function(e) {
id = $(this).attr("id");
$.ajax({
type: "GET",
url: '/gui/details/' + id,
success: function (result) {
$('.details').html(result);
},
});
});
</script>
I'm then trying to use this id to reload the template here -
<div class="details">
{% include 'gui/details.html' %}
</div>
Here is the view for generating the details -
def display_details(request, list_id):
qs_details = Details.objects.filter(owner=request.user, list=list_id)
return render(request, 'gui/details.html', {'qs_details': qs_details,})
Currently when I click anything on my list it doesn't do anything.
Related
I have followed a tutorial to utilise AJAX to validate an input field before attempting to submit. I have it working on my django built site; however, I have been using toasts to alert the user to other actions and did not want to get way from this.
$("#id_hub_name").focusout(function (e) {
e.preventDefault();
// get the hubname
var hub_name = $(this).val();
// GET AJAX request
$.ajax({
type: 'GET',
url: "{% url 'validate_hubname' %}",
data: {"hub_name": hub_name},
success: function (response) {
// if not valid user, alert the user
if(!response["valid"]){
alert("You cannot create a hub with same hub name");
var hubName = $("#id_hub_name");
hubName.val("")
hubName.focus()
}
},
error: function (response) {
console.log(response)
}
})
})
This is my current JS, I want to change the alert function to use toasts instead.
In my base.html I use the following to listen for toasts and create them.
{% if messages %}
<div class="message-container">
{% for message in messages %}
{% with message.level as level %}
{% if level == 40 %}
{% include 'includes/toasts/toast_error.html' %}
{% elif level == 30 %}
{% include 'includes/toasts/toast_warning.html' %}
{% elif level == 25 %}
{% include 'includes/toasts/toast_success.html' %}
{% else %}
{% include 'includes/toasts/toast_info.html' %}
{% endif %}
{% endwith %}
{% endfor %}
</div>
{% endif %}
Thanks in advance
You just need to append the html element for the toast.
First of all, loose the {% if messages %}, make sure <div class="message-container"> is always present in your template. If there are no messages, it will just be an empty div.You also need to add the templates for the toasts in js as well, so that you can just append the toasts from JS.
Now you can just append the template for the toast after your ajax response.
something like:
function show_alert_from_js(alert_type, text) {
msg = `<<your template here>>${text}`; // to render the text message to show.
msg_html = $.parseHTML(msg);
$('.message-container').append(msg_html);
}
$.ajax({
type: 'GET',
...
success: function (response) {
if(!response["valid"]){
show_alert_from_js("error", "You cannot create a hub with same hub name")
...
})
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.
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();
}
Sorry if the title isn't very clear. I have search engine that works with ajax function. Right now if I type t in a search box, the tags that contain the word t shows up(ex if I type t, then test shows up) but thing is after I delete the word t all the tags show up in the result part. Does this make sense? if I'm not clear I'll post the picture. I'm not sure why or how to fix this.
Here;s my code.
<h3>Search</h3>
{% csrf_token %}
<input type="text" id="search" name="search" onkeyup="handle_keyup()"/>
<ul id="search-results">
</ul>
Here I can't delete search-results as this will show the search results but on this section when nothing is typed still all the tags show up. (it only shows all when I finish using search bar)
my ajax
function handle_keyup() {
$.ajax({
type: "POST",
url: "/search/",
data: {
'search_text' : $('#search').val(),
'csrfmiddlewaretoken' : $("input[name=csrfmiddlewaretoken]").val()
},
success: searchSuccess,
dataType: 'html'
});
};
function searchSuccess(data, textStatus, jqXHR)
{
$('#search-results').html(data);
}
problem is probably occurring from up there, but I'll post the back end as well. This is python django framework.
def search_titles(request):
# categories = SearchQuerySet().autocomplete(content_auto=request.POST.get('search_text', ''))
categories = Category.objects.filter(name__icontains=request.POST.get('search_text', ''))
return render_to_response('main/ajax_search.html', {'categories' : categories})
ajax_Search.html
{% if categories.count > 0 %}
{% for category in categories %}
<li>{{ category.name }}</li>
{% endfor %}
{% else %}
<li>None to show!</li>
{% endif %}
thanks in advance
This is happening because when the user "deletes" the word, your handle_keyup function is fired, sending a search request of '' to the server.
The server then looks for the empty string '' in the category names and finds it in all of them.
One approach is for the server to check if the search text is empty, and if it is, return nothing. Something like:
def search_titles(request):
txt = request.POST.get('search_text', '')
if txt:
categories = Category.objects.filter(name__icontains=txt)
else:
categories = []
return render_to_response('main/ajax_search.html', {'categories' : categories})
When I select the "Like" button, the button updates properly. However, the "like count" updates the count for the first image only, instead of the image I selected.
Any ideas how to make only the selected image's like count update as the button does?
Thank you in advance!
html:
{% for photo in photos %}
<img src="{{ photo.get_photo_url }}" />
<input class="like_btn" photo="{{ photo.pk }}" value="{% if user.username in photo.get_likers %}Liked{% else %}Like{% endif %}" type="button" />
0
{% endfor %}
jquery:
$('.like_btn').click(function(e){
e.preventDefault();
var $like_btn = $(this);
$.ajax({
type: "POST",
url: "{% url 'like_ajax' %}",
data: {
"photo_pk": $(this).attr("photo"),
csrfmiddlewaretoken: "{{ csrf_token }}",
},
dataType: "json",
success: function(data) {
if (data.viewer_has_liked) {
$like_btn.val("Liked");
$('#like_count').html(data.like_count);
} else {
$like_btn.val("Like");
$('#like_count').html(data.like_count);
}
},
error: function (rs, e) {
}
});
});
Every photo has the same id for its like count:
{% for photo in photos %}
0
{% endfor %}
Therefore, only the first is recognized as the 'real' #like_count
Since you have a primary key for the photo, you could make the ids distinct by incorporating the photo.pk:
0
EDIT:
Rather than changing the id for each like count, make it into a class and adjust the JavaScript. Try these changes:
In HTML, change this:
0`
To this:
0
In JavaScript, change this:
if (data.viewer_has_liked) {
$like_btn.val("Liked");
$('#like_count').html(data.like_count);
} else {
$like_btn.val("Like");
$('#like_count').html(data.like_count);
}
To this:
if (data.viewer_has_liked) {
$like_btn.val("Liked");
$like_btn.next('.like_count').html(data.like_count);
} else {
$like_btn.val("Like");
$like_btn.next('.like_count').html(data.like_count);
}
This changes will make the like counts a class (.like_count). Then in the JavaScript, you will choose the next selector (after $like_btn) that matches .like_count.
the <a> tags in loop have the same id which is conflict, so set an unique index in <a> tag property for jquery selector