I have a page that displays some information about website admins such as username, skills, Instagram profile and bio. The admins are able to edit their profile information and the update is being saved using JavaScript fetch. When I click on the save button everything except the Instagram profile which is a URLField gets updated. For Instagram element to be updated I need to reload the page. How can I make it get updated without reloading the page? Everything is correct in the console log.
about.js:
document.addEventListener("DOMContentLoaded", function(){
const button = document.querySelectorAll("#edit_profile")
button.forEach(function(button){
button.onclick = function(){
const username = document.getElementById(`username_${memberID}`);
const skills = document.getElementById(`skills_${memberID}`);
const bio = document.getElementById(`bio_${memberID}`);
var instagram = document.getElementById(`instagram_${memberID}`).href;
let edit_username = document.createElement("textarea");
edit_username.setAttribute("rows", "1");
edit_username.innerHTML = username.innerHTML
edit_username.id = `edit_username_${memberID}`;
edit_username.className = `form-control username ${usernameID}`;
let edit_skills = document.createElement("textarea");
...
let edit_instagram = document.createElement("textarea");
edit_instagram.setAttribute("rows","1");
edit_instagram.innerHTML = instagram;
edit_instagram.id = `edit_instagram_${memberID}`;
edit_instagram.className = "form-control social-media";
const saveButton = document.createElement("button");
saveButton.innerHTML = "Save";
saveButton.id = `saveButton_${memberID}`;
saveButton.className = "btn btn-success col-3";
saveButton.style.margin = "10px";
document.getElementById(`edit_${memberID}`).append(edit_username);
...
document.getElementById(`edit_${memberID}`).append(edit_instagram);
document.getElementById(`edit_${memberID}`).append(saveButton);
// When the save button is clicked
saveButton.addEventListener("click", function(){
edit_username = document.getElementById(`edit_username_${memberID}`);
...
edit_instagram = document.getElementById(`edit_instagram_${memberID}`);
fetch(`/edit_profile/${memberID}`,{
method: "POST",
body: JSON.stringify({
username: edit_username.value,
skills: edit_skills.value,
instagram: edit_instagram.value,
bio: edit_bio.value,
})
})
.then(response => response.json())
.then(result => {
console.log(result);
if(result[`error`]){
cancel(memberID)
}
else {
username.innerHTML = result.username;
secusername.innerHTML = result.username;
skills.innerHTML = result.skills;
instagram = result.instagram;
bio.innerHTML = result.bio;
}
})
})
}
});
})
about.html:
{% for member in team_members %}
<div class="col" id="border">
<!--If user is admin, show edit button-->
{% if user.is_superuser %}
<div class="position-relative" id="edit_button_{{member.id}}" style="display: block;">
<button class="btn btn-lg position-absolute top-0 end-0" id="edit_profile" data-id="{{member.id}}" data-username="{{member.username}}">
<i class="fa fa-edit fa-solid" style="color: white; margin-right: 5px;"></i></button>
</div>
{% endif %}
<!--Edit form-->
<div class="form-group" id="edit_{{member.id}}">
</div>
<!--Display username,skills,socials and bio-->
<div id="remove_{{member.id}}" style="display: block;">
<h3 class="username" id="username_{{member.id}}">{{member.username}}</h3>
<p class ="skills" id="skills_{{member.id}}">{{member.skills}}</p>
<p><a class="social-media" href="{{member.instagram}}" id="instagram_{{member.id}}"><i class="fa-brands fa-instagram fa-solid" style="color: #e3c142; margin-right: 5px;"></i></a>
<a class="social-media" href="{{member.itch_profile}}" id="itch_{{member.id}}"><i class="fa-brands fa-itch-io" style="color: #e3c142;"></i></a>
<div class="bio">
<strong class="username" id="secusername_{{member.id}}" style="font-size: large;">{{member.username}}, </strong><p id="bio_{{member.id}}">{{member.bio}}</p>
</div>
</div>
</div>
</div>
{% endfor %}
views.py:
#csrf_exempt
def edit_profile(request, member_id):
if request.method != "POST":
return JsonResponse({"error": "POST request required."}, status=400)
team_members = Team.objects.get(id = member_id)
body_unicode = request.body.decode('utf-8')
body = json.loads(body_unicode)
username = body['username']
skills = body['skills']
instagram = body['instagram']
itch_profile = body['itch_profile']
bio = body['bio']
Team.objects.filter(id=member_id).update(username=f'{username}',skills=f'{skills}',instagram=f'{instagram}',itch_profile=f'{itch_profile}',bio=f'{bio}')
return JsonResponse({"message": "Successful", "username": username, "skills": skills, "instagram":instagram, "itch_profile":itch_profile, "bio": bio}, status=200)
You're assigning the instagram variable to the href attribute of the edit_instagram element, rather than its value. Since the fetch request is sending the value of the edit_instagram element, the Instagram URL will not be updated in the backend if the instagram variable is assigned to the href attribute.
So you can change the line of code where you assign the instagram variable to the following:
var instagram = document.getElementById(`instagram_${memberID}`).value;
Also, you need to update the 'instagram' element value after successful fetch call:
instagram.href = result.instagram;
This should update the Instagram URL field in the backend without requiring a page reload.
Assigned the instagram variable to the element itself instead of its href:
var instagram = document.getElementById(`instagram_${memberID}`)
Then, updated the href after the fetch call as Nova suggested:
instagram.href = result.instagram;
Related
I am new to jQuery. I have implemented a "load more" button on my blog app using jQuery, however the categories tags doesn't get displayed on the html when I click on that button.
Everything works fine so far, I can't just display the tags on the post card, it keeps returning undefined.
Note: I'm getting my categories from a many to many field relationship
Here are my views:
def home(request):
post = BlogPost.objects.all()[0:5]
total_post = BlogPost.objects.count()
context = {'post': post, 'total_post':total_post}
return render(request,'blog/home.html', context)
def load_more(request):
# get total items currently being displayed
total_item = int(request.GET.get('total_item'))
# amount of additional posts to be displayed when i click on load more
limit = 3
posts = list(BlogPost.objects.values()[total_item:total_item+limit])
print(BlogPost.objects.all())
data = {
'posts':posts,
}
return JsonResponse(data=data)
Template:
<div class="blogpost-container">
<div class="blogposts" id="blog-content">
{% for post in post %}
<div class="post">
<img id="img-src" src="{{post.image.url}} " image-url="{{post.image.url}}" alt="">
<p><strong>{{post.title}}</strong></p>
{% for category in post.category.all%}
<h3>{{category}}</h3>
{%endfor%}
<a id="post-detail-link" href="{% url 'detail' post.id %}" detail-url="{% url 'detail' post.id %}"><h2>{{post.summary}}</h2></a>
</div>
{%endfor%}
</div>
</div>
<div class="add-more" data-url='{% url "load_more" %}'id="add-btn">
<button type="button" class="more-content">load more</button>
</div>
<div class="alert no-more-data" role="alert" id="alert">
No more post to load!!!
</div>
{{total_post|json_script:"json-total"}}
JS file:
const loadBtn = document.getElementById('add-btn')
const total_post = JSON.parse(document.getElementById('json-total').textContent);
const alert = document.getElementById('alert')
function loadmorePost(){
const content_container = document.getElementById('blog-content');
var _current_item =$('.post').length;
$.ajax({
url:$('.add-more').attr('data-url'),
type:'GET',
data:{
'total_item':_current_item
},
beforeSend:function(){
alert.classList.add('no-more-data')
},
success:function(response){
const data = response.posts
alert.classList.add('no-more-data')
data.forEach(posts => {
const imageurl = 'media/'+posts.image
const detailurl = 'post/'+posts.id;
const category = posts.category;
content_container.innerHTML +=`<div class="post" id=${posts.id}>
<img id="img-src" src=${imageurl} image-url="{{post.image.url}alt="">
<p><strong>${posts.title}</strong></p>
<h3>${category}</h3>
<a id="post-detail-link" href=${detailurl}><h2>${posts.summary}</h2></a>
</div>`
})
if (_current_item == total_post){
alert.classList.remove('no-more-data')
loadBtn.classList.add('no-more-data')
}
else{ loadBtn.classList.remove('no-more-data')
alert.classList.add('no-more-data')
}
},
error:function(err){
console.log(err);
},
});
};
loadBtn.addEventListener('click', () => {
loadmorePost()
});
I want to make a system of likes on the site, and I need to create an entry in the table on the button. When a person clicks on like, the table writes row 1 and when dislike 0
views.py
def forum(requset):
model = Quetions.objects.all()
answer = Answer.objects.all()
count = Answer.objects.all().count()
count_answer = Quetions.objects.all().count()
paginator = Paginator(model, 1) # Show 25 contacts per page.
page_number = requset.GET.get('page')
question_id = requset.GET.get('id',False)
page_obj = paginator.get_page(page_number)
requestanswer = requset.GET.get('id',False)
like_disli = like.objects.filter(like_dislike = "1").count()
dislike = like.objects.filter(like_dislike = "0").count()
createlike =
objects = {
'model': page_obj,
'answer':answer,
'count':count,
'count_question':count_answer,
'page_obj':page_obj,
'question':question_id,
'id':model,
'request':requestanswer,
'like':like_disli,
'dislike':dislike,
'createlike':createlike,
}
return render(requset,'forum.html',objects)
forum.html
<span>
<i class="fas fa-thumbs-up" style="color: blue;margin-right: 5px;" onclick="incrementClick()"></i>{{like}}<i class="fas fa-thumbs-down" style="color: red;margin-right: 5px;margin-left: 10px;" onclick="dislikeclick()"></i>{{dislike}}
</span>
{% block js %}
<script>
var a = "{{createlike}}"
function incrementClick() {
a
}
function dislikeclick() {
dislikedisplay(++dislikecounter);
}
function updateDisplay(val) {
document.getElementById("counter-label").innerHTML = val;
}
function dislikedisplay(val){
document.getElementById("counter").innerHTML = val
}
</script>
{% endblock js %}
tell me how to do it???
I am fetching a json response from my django response by this url /inbox/<str:username> to get a json response of all the messages in the conversation with that user.
The problem starts with the inbox page which holds the threads and chatbox on the same page like instagram which looks like this
but as it can be seen that I want the url to be like with the username. Let's say when I click on thread with dummy I want the url to be like "inbox/dummy" but in this my url is "/inbox" which will not let me initiate the socket for messaging, my views.py that renders this inbox template is
views for inbox
thread_objs= Thread.objects.by_user(user=request.user)
l=len(thread_objs)
chat_objs=[]
for i in range(l):
chat_objs.append(list(thread_objs[i].chatmessage_set.all()).pop())
chat_objs_serialized=[]
for i in range(l):
chat_objs_serialized.append(json.dumps(ChatMessageSerializer(chat_objs[i]).data))
for i in range(l):
print(chat_objs_serialized[i])
thread_objs_list=[]
for i in range(l):
thread_objs_list.append(json.dumps(ThreadSerializer(thread_objs[i]).data))
return render(request,'uno_startup/inbox.html',context={"Threads":thread_objs_list,"Messages":chat_objs_serialized})
now when I click a thread it's content should load on the right side of screen as with the javascript of inbox.html that is this page in this image.
javascript of inbox
<body>
<div class='container'>
<div class='row'>
<div class="col-md-4" id ="Threadholder">
<ul id ="Threadbox">
{% for object in threads %}
<li>{% if user != object.first %}{{ object.first }}{% else %}{{ object.second }}{% endif %}</li>
{% endfor %}
</ul>
</div>
<div class="col-md-8" id="Chatholder" >
<ul id="Chatbox">
</ul>
<form id="form" method="POST">
<input type="hidden" value="{{ user.username }}" id="myusername">
<input type="text" id="chat_message">
<input type="submit" class="btn btn-primary">
</form>
</div>
</div>
</div>
<script>
var threads={{ Threads|safe }};
var messages={{ Messages|safe }};
const l=threads.length
const threadholder=$("#Threadbox")
for(i=0;i<l;i++){
var data=JSON.parse(threads[i])
var Message=JSON.parse(messages[i])
var username =data.second.username
if (username=="{{ user.username }}"){
username=data.first.username
}
var thread=document.createElement("li")
var main=document.createElement("a")
var div=document.createElement("div")
var username_holder=document.createElement("p")
div.className="thread"
var p=document.createElement("p")
p.innerText=Message.message
username_holder.innerText=username
div.appendChild(username_holder)
div.appendChild(p)
main.appendChild(div)
thread.appendChild(main)
threadholder.append(thread)
};
function add_message(message){
message=JSON.parse(message)
const chatholder=$("#Chatbox")
console.log(message.user.username)
const chat_message= document.createElement("li")
var div= document.createElement("div")
var p = document.createElement("p")
var sender=message.user.username
var text=message.message
p.innerText=text
div.appendChild(p)
chat_message.appendChild(div)
if(sender=="{{ user.username }}"){
chat_message.className="user"
}
else{
chat_message.className="other"
}
chatholder.prepend(chat_message)
}
$(document).ready(function(){
$("li").click(function(){
$("#Chatbox").empty()
var other_user= this.children[0].children[0].children[0].innerText
fetch(`/inbox/${other_user}`).then(response => response.json())
.then(data => data.messages.reverse().forEach(add_message))
})
})
and this is the function that returns the json response
view for json response
thread=Thread.objects.get_or_new(user=request.user,other_username=username)
messages=thread[0].chatmessage_set.all()
l= len(messages)
messages_serialized=[]
for i in range(l):
messages_serialized.append(json.dumps(ChatMessageSerializer(messages[i]).data))
print(messages)
return JsonResponse({"messages":messages_serialized})
and this Chat function is called via this url /inbox/<str:username>
I want a method that can help me get the thread open without reloading, and updates the url, I have used AJAX but it didn't help as it also took to me the page where it gave me the Json Response from django, changing the original page.
The failed AJAX implementation
<script>
var threads={{ Threads|safe }};
var messages={{ Messages|safe }};
const l=threads.length
const threadholder=$("#Threadbox")
for(i=0;i<l;i++){
var data=JSON.parse(threads[i])
var Message=JSON.parse(messages[i])
var username =data.second.username
if (username=="{{ user.username }}"){
username=data.first.username
}
var thread=document.createElement("li")
var main=document.createElement("a")
var div=document.createElement("div")
var username_holder=document.createElement("p")
div.className="thread"
var p=document.createElement("p")
p.innerText=Message.message
username_holder.innerText=username
div.appendChild(username_holder)
div.appendChild(p)
main.appendChild(div)
thread.appendChild(main)
threadholder.append(thread)
};
function add_message(message){
message=JSON.parse(message)
const chatholder=$("#Chatbox")
console.log(message.user.username)
const chat_message= document.createElement("li")
var div= document.createElement("div")
var p = document.createElement("p")
var sender=message.user.username
var text=message.message
p.innerText=text
div.appendChild(p)
chat_message.appendChild(div)
if(sender=="{{ user.username }}"){
chat_message.className="user"
}
else{
chat_message.className="other"
}
chatholder.prepend(chat_message)
}
$(document).ready(function(){
$("li").click(function(){
$("#Chatbox").empty()
var other_user= this.children[0].children[0].children[0].innerText
<script>
var threads={{ Threads|safe }};
var messages={{ Messages|safe }};
const l=threads.length
const threadholder=$("#Threadbox")
for(i=0;i<l;i++){
var data=JSON.parse(threads[i])
var Message=JSON.parse(messages[i])
var username =data.second.username
if (username=="{{ user.username }}"){
username=data.first.username
}
var thread=document.createElement("li")
var main=document.createElement("a")
var div=document.createElement("div")
var username_holder=document.createElement("p")
div.className="thread"
var p=document.createElement("p")
p.innerText=Message.message
username_holder.innerText=username
div.appendChild(username_holder)
div.appendChild(p)
main.appendChild(div)
thread.appendChild(main)
threadholder.append(thread)
};
function add_message(message){
message=JSON.parse(message)
const chatholder=$("#Chatbox")
console.log(message.user.username)
const chat_message= document.createElement("li")
var div= document.createElement("div")
var p = document.createElement("p")
var sender=message.user.username
var text=message.message
p.innerText=text
div.appendChild(p)
chat_message.appendChild(div)
if(sender=="{{ user.username }}"){
chat_message.className="user"
}
else{
chat_message.className="other"
}
chatholder.prepend(chat_message)
}
$(document).ready(function(){
$("li").click(function(){
$("#Chatbox").empty()
var other_user= this.children[0].children[0].children[0].innerText
$.ajax({
type: "GET",
url: {% url 'Chat' username=other_user %},
data: {'Messages': messages}
})
.done(function(response) {
console.log(reposne)
});
})
})
})
})
Your Django view is reloading the page because it's returning a response of content type HTML instead of, say, JSON.
Instead of
return render(request,'uno_startup/inbox.html',context={"Threads":thread_objs_list,"Messages":chat_objs_serialized})
Do something like
from django.http import JsonResponse
...
return JsonResponse({"Threads": thread_objs_list, "Messages": chat_objs_serialized})
You should still fetch this response from the front-end using JavaScript/AJAX.
As for how to change the URL without inducing a page refresh, refer to this answer.
<i class="fa fa-ban color-red"></i> Approve Payment
<i class="fa fa-ban color-red"></i> Reject Payment
<script>
if (filterpayment) {
url += '&filterpayment=' + encodeURIComponent(filterpayment);
}
</script>
After using filter" my URL will be like this
http://localhost/index.php?route=sales/filterpayment&user_token=XXXXXX&filterpayment=2&page=2
For Page 2 is "pagination"
What i wanted is that , after perform an action (such as clicking approve), how do i reset it without deleting "page2"
What i wanted after clicking : approve
http://localhost/index.php?route=sales/filterpayment&user_token=XXXXXX&page=2
What i tried :
url = 'index.php?route=sales/filterpayment&user_token={{ user_token }}';
location = url;
but it will straight just reset the "page2" in the URL and becoming this
http://localhost/index.php?route=sales/filterpayment&user_token=XXXXXX
Use the searchParams
let url = new URL("http://localhost/index.php?route=sales/filterpayment&user_token=XXXXXX&page=2")
let filterpayment = 2;
if (filterpayment) {
url.searchParams.set("filterpayment",encodeURIComponent(filterpayment));
}
console.log(url)
filterpayment = 0;
if (filterpayment) {
url.searchParams.set("filterpayment",encodeURIComponent(filterpayment));
}
else {
url.searchParams.delete("filterpayment");
}
console.log(url)
I want to create a pop up which opens up clicking the button 'Dissolve'. The pop up should say: 'Are you sure you want to delete this field?' and have two buttons: Okay and Cancel. If Cancel is chosen it should simply close the pop up. If Okay is clicked, it should redirect to the previous page and delete that job on the previous page's table.
My current code for the button is:
<button type="button" class="btn btn-primary">Dissolve</button>
My current code for the job in module.py is:
class Job(models.Model):
def __unicode__(self):
return self.name
name = models.CharField('Job Name',max_length=128)
# when the job was created
date_created = models.DateTimeField('Date Created', auto_now=True)
# what entity/organization needs this job?
client_organization = models.CharField('What organization do you represent?', max_length=64)
# short description
description = models.TextField('Job Description', max_length=256)
# end product to be delivered
deliverable = models.TextField('Deliverable', max_length=256)
# when Job is due for completion
duedate = models.DateTimeField('Date Due')
# all persons who may be affected by project
#stakeholders = models.TextField('Stakeholders')
# important technical requirements
#additional_information = models.TextField('Additional Information', blank = True)
# budget estimate
#budget = models.CharField('Budget', max_length=64)
# file attachments
#attachments = models.FileField(upload_to='job', blank = True)
creator = models.ForeignKey(User,related_name = 'jobs')
organizations = models.ManyToManyField(Organization, through = 'JobRequest', blank=False, null=True)
#organizations = models.CharField(default="nothing",null=True,max_length = 256)
contact_information = models.CharField('Contact Information', max_length = 256, blank = False, null=True)
skill_required = models.CharField('Volunteer skills required', max_length=256, blank = False, null=True)
hours_day = models.CharField('Number of hours per day', max_length=256, blank = False, null=True)
# Job is closed after a jr is confirmed
closed = models.BooleanField(default = False)
# some tags to determine what organizations to submit job to
categories = models.ManyToManyField(Category, related_name = 'jobs')
#categories = models.CharField(default="nothing",null=True, max_length = 256)
status = models.IntegerField(default = 0, choices = ((0, 'Pending'), (1, 'Approved'), (2, 'Disapproved'), (3, 'Closed')))
active = models.BooleanField(default = False)
class Meta:
permissions = (
( 'view_job','Can view Job' ),
( 'edit_job','Can edit Job'),
( 'is_creator', 'Is a creator of Job')
)
My current code for the previous page's HTML is:
<div class="col-sm-6">
<div class="panel panel-primary">
<div class="panel-heading">
Your Jobs
</div>
<div class="panel-body">
<ul class="list-group">
{% for job in jobs %}
<a class="list-group-item" href="{% url 'job_dash' job.id %}">
{{ job.name }}
</a>
{% endfor %}
<br>
<a href = '/job_creation' class="btn btn-danger"> <i class="fa fa-
plus"></i> Create Job</a>
</ul>
</div>