AJAX update variable in html django - javascript

I'm trying to update a variable in an html page after it has been updated using an AJAX call:
{% for q in questions %}
{% if qdelete == forloop.counter %}
<div align= Center>
<button type="submit" class="btn btn-primary btn-small" id="qyesbtn" name="qyesbtn" value="qyesbtn_{{q.id}}">Yes »</button>
</div>
<div align= Center>
<button type="submit" class="btn btn-primary btn-small" id="qnobtn" name="qnobtn" value="qnobtn">No »</button>
</div>
{% else %}
<button type="button" id="qbtn" class="btn btn-primary btn-large" name="qid" value="{{forloop.counter}}" onclick="SetDeleteNum({{forloop.counter}})">Delete »</button>
{% endif %}
{% endfor %}
<script>
function SetDeleteNum(d) {
var num = -1
num = d
console.log('num: '+num)
var page = $(this)
$.ajax({
type: "POST",
url: "{% url 'home' %}",
data: {
'csrfmiddlewaretoken': $('input[name="csrfmiddlewaretoken"]').val(),
'qid': num
},
dataType: 'json',
success: function (data) {
console.log('aa'+JSON.stringify(data))
page.html(data);
},
error: function(e){
console.log('err: '+JSON.stringify(e))
}
});
}
</script>
The value qdelete should be updated to 'num' after the AJAX call but it is still as before although I can see from the logs that the qdelete has the new value assigned but it simply not displayed in the page. I also tried to put the new 'data' in the new html using the line 'page.html(data);' but no luck. Any idea?

I found the solution simply I put ids on all the buttons:
<div align= Center id="qbtn_{{forloop.counter}}" style="display:block">
<button type="button" class="btn btn-primary btn-large" name="qid" value="{{forloop.counter}}" onclick="SetDeleteNum({{forloop.counter}})">Delete »</button>
</div>
<div align= Center id="ybtn_{{forloop.counter}}" style="display:none">
<button type="submit" class="btn btn-primary btn-small" id="qyesbtn" name="qyesbtn" value="qyesbtn_{{q.id}}">Yes »</button>
</div>
<div align= Center id="nbtn_{{forloop.counter}}" style="display:none">
<button type="button" class="btn btn-primary btn-small" id="qnobtn" name="qnobtn" value="qnobtn" onclick="SetDeleteNum({{forloop.counter}})">No »</button>
</div>
and then I show/hide the buttons according to the counter value:
function SetDeleteNum(d) {
var num = -1
num = d
console.log('num: '+num) //code to refresh the page
//var page_y = $( document ).scrollTop();
//window.location.href = window.location.href + '?page_y=' + page_y;
//var div = $(this).getElementById("qbtn_"+num.toString())
console.log('dd: '+'-')
div_q = document.getElementById("qbtn_"+num.toString())
div_y = document.getElementById("ybtn_"+num.toString())
div_n = document.getElementById("nbtn_"+num.toString())
//div.disabled = true
if(div_q.style.display == 'block'){
div_y .style.display = 'block';
div_n .style.display = 'block';
div_q.style.display = 'none';
}
else{
div_q.style.display = 'block';
div_n .style.display = 'none';
div_y .style.display = 'none';
}
}
hope it helps to others

Related

How can I addEventListener to multiple buttons which are displayed via a for loop?

I have a page that displays social media posts from users and all posts have an Edit button. When the Edit button is clicked on, a form with a textarea pre-filled with the current content and a submit input is displayed.
The problem is that regardless of which post's Edit button I click, always the first post is changing. I guess I should add an "id" somewhere to track which post is being edited but I couldn't figure out how to do that. Or is there another solution?
views.py:
def index(request):
post_list = AllPost.objects.all().order_by("date").reverse()
paginator = Paginator(post_list, 10) # Show 10 posts per page.
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, "network/index.html", {
"posts": post_list,
"page_obj": page_obj
})
def edit(request, id):
if request.method == "POST":
new_content = request.POST["new_content"]
updated_post = AllPost.objects.filter(id = id)
updated_post.update(content = new_content)
return JsonResponse({}, status = 201)
return JsonResponse({"error": "Bad Request"}, status = 400)
index.html:
{% for post in page_obj %}
{{ post.full_name|upper }}<br>
<div class="frame">
<h4>{{post.user.username}}</h4>
{% if post.user == user %}
<button class="btn btn-sm btn-outline-primary" id="edit">Edit</button>
{% endif %}
<div id="content">{{post.content}}</div>
<form action="{% url 'edit' post.id %}" method="post" id="edit_post" style="display: none;">
{% csrf_token %}
<div class="form-group"><textarea id="new_content" name="new_content" cols="30"></textarea></div>
<input class="btn btn-sm btn-primary" id="save" type="submit" value="Save">
</form>
<div class="grey" id="timestamp">{{post.date}}</div>
<div class="grey">{{post.likes}}</div>
Comment
</div>
{% endfor %}
network.js
document.addEventListener("DOMContentLoaded", () => {
document.querySelector("#content").innerHTML = localStorage.getItem("content");
document.querySelectorAll("#edit").forEach(button => {
button.onclick = () => {
const content = document.querySelector("#content").innerHTML;
document.querySelector("#content").style.display = "none";
document.querySelector("#edit_post").style.display = "block";
document.querySelector("#new_content").value = content;
}
});
document.querySelector("#edit_post").onsubmit = (event) => {
let content = document.querySelector("#new_content").value;
document.querySelector("#content").innerHTML = content;
document.querySelector("#content").style.display = "block";
document.querySelector("#edit_post").style.display = "none";
event.preventDefault();
localStorage.setItem("content", content);
};
});
Just remove the absolute id-selectors because with an absolute id-selector you just get always the first element with that id. So change it for a relative class-selector instead. Also, I recommend you to use addEventListener instead of on<event>.
Change the .html to the following:
{% for post in page_obj %}
{{ post.full_name|upper }}<br>
<div class="frame">
<h4>{{post.user.username}}</h4>
{% if post.user == user %}
<button class="btn btn-sm btn-outline-primary edit">Edit</button>
{% endif %}
<div class="content">{{post.content}}</div>
<form action="{% url 'edit' post.id %}" method="post" class="edit_post" style="display: none;">
{% csrf_token %}
<div class="form-group"><textarea class="new_content" name="new_content" cols="30"></textarea></div>
<input class="btn btn-sm btn-primary" id="save" type="submit" value="Save">
</form>
<div class="grey" id="timestamp">{{post.date}}</div>
<div class="grey">{{post.likes}}</div>
Comment
</div>
{% endfor %}
Change the .js to the following:
document.addEventListener("DOMContentLoaded", () => {
const content = localStorage.getItem("content")
if (content) document.querySelector(".content").textContent = JSON.parse(content)
Array.from(document.querySelectorAll(".edit")).forEach(button => {
button.addEventListener('click', event => {
const target = event.target
const frame = target.closest('.frame')
const content = frame.querySelector('.content')
const edit_post = frame.querySelector('.edit_post')
edit_post.style.display = 'block'
const new_content = frame.querySelector('.new_content')
new_content.value = content.textContent
content.style.display = 'none'
})
const form = button.closest('.frame').querySelector('.edit_post')
form.addEventListener('submit', event => {
const target = event.target
const frame = target.closest('.frame')
const content = frame.querySelector('.content')
const new_content = frame.querySelector('.new_content')
content.textContent = new_content.value
localStorage.setItem('content', JSON.stringify(new_content.value))
content.style.display = 'block'
const edit_post = frame.querySelector('.edit_post').style.display = 'none'
event.preventDefault()
})
});
});

Django, Ajax and JS Toggle Like and Unlike Icon on Button Click

0
I followed a solution on how to get Django Like and Unlike button not to reload the page on click. The solution i found works but only with TEXT toggle (Like and Unlike) and i want an Icon Toggle (Like and Unlike Icon).
I am new to Django Backend and Ajax, i will be happy if someone can help on how to deal with this. Thanks in Advance.
$( document ).ready(function() {
$('.like-form').submit(function(e){
e.preventDefault()
const post_id = $(this).attr('id')
const likeText = $(`.like-btn${post_id}`).text()
const trim = $.trim(likeText)
const url = $(this).attr('action')
let res;
const likes = $(`.like-count${post_id}`).text()
const trimCount = parseInt(likes)
$.ajax({
type: 'POST',
url: url,
data: {
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
'post_id':post_id,
},
success: function(response) {
if(trim === 'Unlike') {
$(`.like-btn${post_id}`).text('Like')
res = trimCount - 1
} else {
$(`.like-btn${post_id}`).text('Unlike')
res = trimCount + 1
}
$(`.like-count${post_id}`).text(res)
},
error: function(response) {
console.log('error', response)
}
})
});
});
<!-- Like Button -->
<li class="list-inline-item">
<form action="{% url 'posts:like-post-view' %}" method="POST" class='like-form' id='{{obj.id}}'>
{% csrf_token %}
<input type="hidden" name="post_id" value={{obj.id}}>
<button type="submit" class="btn btn-link g-color-gray-dark-v5 g-color-red--hover text-red p-0 border-0 btn-outline-light like-btn{{obj.id}}">
{% if user not in obj.liked.all %}
Like
<i class="align-middle mr-1 icon-heart u-line-icon-pro g-font-size-25"></i>
{% else %}
Unlike
<i class="align-middle mr-1 icon-like u-line-icon-pro g-font-size-25"></i>
{% endif %}
</button>
<span class="g-color-gray-dark-v5 g-font-size-15 like-count{{obj.id}}"> {{obj.num_likes}}</span>
</form>
</li>
<!-- End Like Button -->
You can append icons as well inside your success function with text . Also , put like and unlike inside span so that it would be easy to change value .
Demo Code :
$('.like-form').submit(function(e) {
e.preventDefault()
const post_id = $(this).attr('id')
const likeText = $(".like-btn"+post_id).find("i").hasClass("fa-heart-o") ? "Unlike":"Like"//check for class and if true then set value as unlike or like..
const trim = $.trim(likeText)
const url = $(this).attr('action')
let res;
const likes = $(`.like-count${post_id}`).text()
const trimCount = parseInt(likes)
/* $.ajax({
type: 'POST',
url: url,
data: {
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
'post_id': post_id,
},
success: function(response) {*/
if (trim === 'Unlike') {
//use .html to add htmls codes
$(`.like-btn${post_id}`).html('<i class="fa fa-heart" aria-hidden="true"></i>')
res = trimCount - 1
} else {
$(`.like-btn${post_id}`).html('<i class="fa fa-heart-o" aria-hidden="true"></i>')
res = trimCount + 1
}
$(`.like-count${post_id}`).text(res)
/* },
error: function(response) {
console.log('error', response)
}
})*/
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="{% url 'posts:like-post-view' %}" method="POST" class='like-form' id='1'>
<input type="hidden" name="post_id" value=1>
<button type="submit" class="btn btn-link g-color-gray-dark-v5 g-color-red--hover text-red p-0 border-0 btn-outline-light like-btn1">
<!--put texxt inside span-->
<i class="fa fa-heart" aria-hidden="true"></i>
</button>
<span class="g-color-gray-dark-v5 g-font-size-15 like-count1">12</span>
</form>
<form action="{% url 'posts:like-post-view' %}" method="POST" class='like-form' id='2'>
<input type="hidden" name="post_id" value=2>
<button type="submit" class="btn btn-link g-color-gray-dark-v5 g-color-red--hover text-red p-0 border-0 btn-outline-light like-btn2">
<i class="fa fa-heart-o" aria-hidden="true"></i>
</button>
<span class="g-color-gray-dark-v5 g-font-size-15 like-count2">5</span>
</form>

How do i get the id to be added and removed from the particular button clicked?

<script>
$(document).ready(function() {
$("button").on('click', function(argument) {
$("button").attr('id', 'addtocart');
var product_id = $("#product_id").val();
if (product_id!="") {
$.ajax({
type : "POST",
url : "manage-cart.php",
data : 'product_id='+product_id,
success : function (response) {
// action to be performed if successful
$('#addtocart').removeAttr('id');
}
})
}
})
});
</script>
<div class="buttons">
<button class="" type="submit" >
<i class="fa fa-shopping-cart"></i>Add to Cart</button>
</div>
<input type="hidden" id="product_id" value ="5">
<div class="buttons">
<button class="" type="submit" >
<i class="fa fa-shopping-cart"></i>Add to Cart</button>
</div>
<input type="hidden" id="product_id" value ="6">
<div class="buttons">
<button class="" type="submit" >
<i class="fa fa-shopping-cart"></i>Add to Cart</button>
</div>
<input type="hidden" id="product_id" value ="7">
<div class="buttons">
<button type="submit" >
<i class="fa fa-shopping-cart"></i>Add to Cart</button>
</div>
<input type="hidden" id="product_id" value ="8">
this is the script and HTML code I'm working with. When the button is clicked the id is added to all the buttons and that's not the idea I want the id to be added to just the clicked button and removed after execution of the ajax script.
you need to use $(this)
$(document).ready(function() {
$("button").on('click', function(argument) {
var _t = $(this);
_t.attr('id', 'addtocart');
var product_id = $("#product_id").val();
if (product_id!="") {
$.ajax({
type : "POST",
url : "manage-cart.php",
data : 'product_id='+product_id,
success : function (response) {
// action to be performed if successful
_t.removeAttr('id');
}
})
}
})
});
</script>

How do I stop ajax call from refreshing my page?

<form id="review" method="post">
{% csrf_token %}
<button type="submit" id="sbtn" class="btn btn-primary btn-icon-split btn-lg" value="{{ Asin }}" >
<span class="icon text-white-50">
<i class="fas fa-poll-h"></i>
</span>
<span class="text">Fetch Reviews</span>
</button>
</form>
This is my html form on a Django rendered page
<script type="text/javascript">
$(document).on('submit','#review'.function(e){
e.preventDefault();
e.stopPropagation();
$.ajax({
type:'POST',
URL:'/reviews/',
data:{
asin:$('#sbtn').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
},
beforeSend:function() {
$('#loader').removeClass('hidden');
},
complete : function() {
$('#loader').addClass('');
}});
return false;
});
This is the ajax function on the page.
The problem is...the current page is the result of a form on a previous page so as soon as the form-submit event is invoked the page refreshes and data on the page is lost. I tried both
e.preventDefault()
and
e.stopPropagation()
but that doesn't help. I'd like to know if you have some approach or a workaround..Thank you!
To make this work change this part of code:
<button type="submit" id="sbtn" class="btn btn-primary btn-icon-split btn-lg" value="{{ Asin }}" >
Like that:
<button type="button" id="sbtn" class="btn btn-primary btn-icon-split btn-lg" value="{{ Asin }}" >
<button type="submit" id="submit_sbtn" class="d-none">
The submit button is not necessary.
Then change your script to send an ajax request to $('#sbtn') click event. And then submit your form.
$(document).on('submit','#review', function() {
$('#loader').removeClass('hidden');
$.ajax({
method: "POST",
type: "POST",
url: "/reviews/",
data: {
asin:$('#sbtn').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
}
}).done( function( msg ) {
$('#loader').addClass('');
console.log(msg)
}).fail( function(error) {
console.log(error)
})
return false;
})

x-editable resetting fields

i have the following html/php code (php tag ommited)
$user = array(
'name' => Null,
'address' => Null
);
<div id="user">
<a href="#" id="cust_name" data-type="text"
data-pk="'.$user['ag_id'].'" title="Enter customer name">'.$user['name'].'</a>
<a href="#" id="cust_addr" data-type="text"
data-pk="'.$user['ag_id'].'" title="Enter customer address">'.$user['address'].'</a>
<div class="modal-footer">
<button type="button" class="btn btn-default" id="ResetButton">Reset</button>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="SaveButton"
data-dismiss="modal">Save changes</button>
</div>
</div>
could you please complete my resetbutton script, the purpose is to assign null to cust_name and cust_addr after the click.. here's the script
<script>
$.fn.editable.defaults.mode = 'inline';
$(function(){
$('#user a').editable({
url: 'post.php'
});
});
$("#SaveButton").click(function() {
$.ajax({
url: 'db.php',
type: 'POST',
data: {}
});
});
$('#ResetButton').click(function() {
// $('#cust_name').editable('setValue', null); // did not worked
// didn't worked even i added class="myeditable" in my <a> tag
/*
$('.myeditable').editable('setValue', null)
.editable('option', 'pk', null)
.removeClass('editable-unsaved');
*/
});
</script>
This seemed to work.
http://jsfiddle.net/U33kT/
I'm not sure the difference, except that I chose all editables (JS line 6):
$('#user a').editable('setValue', null);
But, I tried with single items:
$('#cust_name').editable('setValue', null);
and it seemed to work as well.
Hope this helps.

Categories

Resources