Displaying comments using Ajax - javascript

i am working on a project using Django. There are lists of users posts in homepage and each post has a comment form. I was able to implement comment properly on views, but the issue now is when I submit a comment it display empty string instead of the comment, the comment display in chrome console. How do i display comment on each post by user when a form is submitted. I attached an image to my questioin to clarify my question.
home.html
<div id="newfeeds-form">
{% include 'ajax_newfeeds_comments.html' %}
</div>
ajax_newfeeds_comments.html
<!-- New Feeds comment Text -->
{% for post in all_images %}
<div class="container newfeeds-comment" id="display-comment">
{% for comment in post.comments_set %}
<div class="row">
<div class="col-1 col-md-1 col-lg-1">
{% if comment.user.profile.profile_pic %}
<img src="{{ comment.user.profile.profile_pic.url }}" class="d-flex rounded-circle" alt="image" height="28" width="28">
{% endif %}
</div>
<div class="col-10 col-md-10 col-lg-10 p-2 ml-1" id="user-commentpost">
<span class="comment-post truncate">
<span class="name text-lowercase">{{ comment.user }}</span>
{{ comment.comment_post }}</span>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
<span class="md-form">
<form enctype="multipart/form-data" class="feeds-form form-inline md-form form-sm" method="POST" action="{% url 'site:home' %}" id="newfeeds-form{{ post.id }}">
{% csrf_token %}
<input type="hidden" value={{post.id}} name="post_comment">
<img src="{{ request.user.profile.profile_pic.url }}" class="rounded-circle avatar-img" height="28" width="28">
<textarea name="comment_post" class="textinput textInput animated fadeIn" placeholder="Add a comment..." required="" id="id_comment_post{{ post.id }}" onkeyup=""></textarea>
<button type="submit" class="submit" id="submit1-{{post.id}}"><i class="fas fa-paper-plane"></i></button>
</form
</span>
Views:
def home_view(request):
#All posts in new feed
all_images = Post.objects.filter(
Q(poster_profile=request.user, active=True)|
Q(poster_profile__from_user__to_user=request.user, active=True)|
Q(poster_profile__to_user__from_user=request.user, active=True)|
Q(poster_profile__profile__friends__user=request.user, active=True)).distinct().exclude(
Q(hide_post=request.user, active=True)|
Q(poster_profile__profile__blocked_users__user=request.user, active=True))
#Comment form homepage
if request.method == 'POST':
post_id = request.POST.get("post_comment")
post_obj = Post.objects.get(pk=post_id)
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.user = request.user
comment.commented_image = post_obj
comment.save()
# messages.info(request,'You submitted a comment')
#return redirect('/')
else:
form = CommentForm()
context = {
'form': form,
'all_images': all_images,
}
if request.is_ajax():
html = render_to_string('ajax_newfeeds_comments.html', context, request=request)
return JsonResponse({'form': html})
return render(request,'home.html', context)
Ajax:
<script type="text/javascript">
//HomeFeeds Comment
$(document).ready(function() {
$('.feeds-form').on('submit', onSubmitFeedsForm);
$('.feeds-form .textinput').on({
'keyup': onKeyUpTextInput,
'change': onKeyUpTextInput
});
function onKeyUpTextInput(event) {
var textInput = $(event.target);
textInput.parent().find('.submit').attr('disabled', textInput.val() == '');
}
function onSubmitFeedsForm(event) {
event.preventDefault();
console.log($(this).serialize());
var form = $(event.target);
var textInput = form.find('.textinput');
var hiddenField = form.find('input[name="post_comment"]');
$.ajax({
type: 'POST',
url: "{% url 'site:home' %}",
data: form.serialize(),
dataType: 'json',
beforeSend: function() {
form.find('.submit').attr('disabled', true);
},
success: function(response) {
$('#newfeeds-form' + hiddenField.val()).html(response.form);
textInput.val('');
var numberOfCommentsElement = $('#number-of-comments');
numberOfCommentsElement.text(parseInt(numberOfCommentsElement.text()) + 1);
},
error: function(rs, e) {
console.log(rs.resopnseText);
},
complete: function() {
textInput.trigger('change');
}
});
}
});
</script>

You don't need ajax actually, you can simply:
let value = $('myInput').val();
$('myCommentContainer').prepend(`
Format the comment as you want ${value}
`)
$('myInput').val('') // To empty the value
now call the ajax normally:
$({
type: 'POST',
url: "{% url 'site:home' %}",
data: form.serialize(),
dataType: 'json',
beforeSend: function() {
form.find('.submit').attr('disabled', true);
},
success: function(response) {}
})
Done, leave the success empty
appending it within the ajax success will make it slower anyway!

Related

how to dynamically show form input fields base on user selection from dropdown options

I have this form that is used to enter student grades per subject now on this form I have 3 dropdown boxes that are dependent on each other, what I want to accomplish is that after the user selects the classroom that the students are in, I want the input fields for each subject to appear on the same form that is only in that class that the user selected so that the user can enter the grades of the students per subject but I am having a hard time figuring out how to implement such behavior. in short,i want to show input fields for subjects base on the classroom the user selected
form.py
<div class="container-fluid">
<form id="result-form" method="post">
{% csrf_token %}
<!-- Modal -->
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel"> {% block modal-title%} Add Result {% endblock%}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12" id="msg8" style="font-size: 2rem; color:rgb(255, 144, 47)"></div>
<div class="col-md-12 form-group p-2">
<label class="form-label">Class Name</label>
{% render_field form.room class+="form-control" %}
</div>
<div class="col-md-12 form-group p-2">
<label class="form-label">Exam Name</label>
{% render_field form.exam class+="form-control" %}
</div>
<div class="col-md-12 form-group p-2">
<label class="form-label">Student</label>
{% render_field form.student class+="form-control select2" %}
</div>
<div class="hidden" id="subject-fields"></div>
<div class="form-group mb-3 pt-2">
<button type="button" id="resBtn" class="btn btn-info" title="Add">Submit</button>
</div>
</div>
</div>
</form>
</div>
{% block script%}
<script>
$(document).ready(function () {
$('#id_room').change(function(){
var url = "{% url 'load_exams' %}"
var class_id = $(this).val();
$.ajax({
url: url,
data: {
'room':class_id
},
success: function(data){
$("#id_exam").html(data)
}
})
})
$('#id_room').change(function () {
var url = "{% url 'load_students' %}"
var class_id = $(this).val();
$.ajax({
url: url,
data: {
'room': class_id
},
success: function (data) {
$("#id_student").html(data)
}
})
})
$('.select2').select2({
placeholder: 'Please Select Here',
width: '100%',
dropdownParent: $('#addmodal')
});
$('#resBtn').click(function () {
let room = $('#id_room').val();
let exam = $('#id_exam').val();
let student = $('#id_student').val();
let csr = $('input[name="csrfmiddlewaretoken"]').val();
if (room == '' && name == '') {
$('#msg4').html('All fields are required').fadeIn('slow');
$('#msg4').delay(7000).fadeOut('slow');
} else {
mydata = {
exam: exam, csrfmiddlewaretoken: csr, room: room, student: student
};
console.log(mydata)
$.ajax({
url: "{% url 'add-result' %}",
data: mydata,
type: 'POST',
success: function (data) {
if (data.status == 'Save') {
$('#msg8').html('Result Successfully Added').fadeIn('slow');
$('#result-form')[0].reset();
$('#msg8').delay(3000).fadeOut('slow');
setTimeout(function () {
$('#addmodal').modal('hide')
}, 3000)
location.reload()
} else {
alert('Error with saving form')
}
}
})
}
});
})
</script>
{% endblock%}
forms.py
# deal with entering results
class ResultForm(forms.ModelForm):
class Meta:
model = Result
fields = ["room", "exam","student","percentage"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["exam"].queryset = Exam.objects.none()
if "room" in self.data:
try:
class_id = int(self.data.get("room"))
self.fields['exam'].queryset = Exam.objects.filter(room=class_id).order_by('name')
except(ValueError,TypeError):
pass
elif self.instance.pk:
self.fields['exam'].queryset = self.instance.classroom.exam_set.order_by('name')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["student"].queryset = Exam.objects.none()
if "room" in self.data:
try:
class_id = int(self.data.get("room"))
self.fields['student'].queryset = Student.objects.filter(room=class_id).order_by('name')
except(ValueError, TypeError):
pass
elif self.instance.pk:
self.fields['student'].queryset = self.instance.classroom.exam_set.order_by('name')
# deal with entering grade per subject
class MarkForm(forms.ModelForm):
class Meta:
model = Mark
fields = ["result", "course","grade"]

How do disable redirecting when I clicking on a button? Django

I am trying to create a like button for my page. thats okey its working but when I click the button page is refreshing. When I click on the like button, I want the counter showing the number of likes to increase. I try used Ajax but I failed. here are my codes..
Views:
def liked_post(request,pk):
post =get_object_or_404(UserPosts, id=request.POST.get("userposts_id"))
liked = False
if post.like_post.filter(id = request.user.id).exists():
post.like_post.remove(request.user)
liked = False
else:
post.like_post.add(request.user)
liked = True
return HttpResponseRedirect(reverse('detail', args=[str(pk)] ))
def detail_post(request,_detail):
postDetail = UserPosts.objects.get(pk = _detail)
liked = False
if postDetail.like_post.filter(id= request.user.id).exists():
liked = True
context= {
"detail":postDetail,
"liked":liked
}
return render(request,"DetailPost.html",context)
Javascript file:
$(document).ready(function () {
//like ajax call
$('.like-form').submit(function (e) {
e.preventDefault();
const userposts_id = $('.like-btn').val();
const token = $('input[name=csrfmiddlewaretoken]').val();
const url = $(this).attr('action')
$.ajax({
method: "POST",
url: url,
headers: { 'X-CSRFToken': token },
data: {
'userposts_id': userposts_id
}
})
})
})
Template:
<form class="btn-group mt-1 like-form" action="{% url 'like_post' detail.pk %}"
method="POST">
{% csrf_token %}
{% if request.user.is_authenticated %}
{% if detail.username_id == request.user.id %}
<button class="btn btn-primary btn-sm" disabled>Like</button>
{% else %}
{% if liked %}
<button class="btn btn-danger btn-sm " type="submit" name="userposts_id"
value="{{ detail.id }}">Unlike</button>
{% else %}
<button class="btn btn-primary btn-sm like-btn"
type="submit" name="userposts_id" value="{{ detail.id }}">Like</button>
{% endif %}
{% endif %}
{% else %}
<span class="px-2 pt-1">
Login to like
</span>
{% endif %}
<span class="bg-dark px-4 pt-1 like-count text-white"> {{total_post_likes}}</span>
</form>
Does anyone have an idea?
You are redirecting to detail page in your like_post view. Instead of redirecting return JsonResponse
def liked_post(request):
if request.is_ajax():
pk = request.POST.get('userposts_id')
post = get_object_or_404(UserPosts,id=pk)
if request.user in post.like_post.all():
liked = False
post.like_post.remove(request.user)
else:
liked = True
post.liked.add(request.user)
return JsonResponse({'liked': liked, 'count': post.like_post.count()})
return redirect('detail')
this will return a json with liked and count .
<span class="bg-dark px-4 pt-1 like-count text-white"> {{total_post_likes}}</span>
Get span to render likes from js
$.ajax({
type: "GET",
url: url,
success: function (response) {
console.log(response) //response will be what you send in jsonresponse in django view
$('.like-count').innerHtml =`${response.count}`
}
})

What event.target will contain if I added submit event listener on the form

I have a lot of forms on the page and when one of them is submitted I want to send request via ajax to the view and have an id of the article and other info. So I need to check if form that has been clicked is the same as event.target. I did something like this but don't know if it is correct(first console.log works but second not):
<div id = "list">
{% for article in news %}
<h1>{{ article.title }}</h1>
<p>{{ article.published }}</p>
<img src = "{{ article.url }}">
<p>
<button>Upvote</button>
<button>Downvote</button>
</p>
<div id="span">
{% with article.upvotes.count as total_upvotes and article.downvotes.count as total_downvotes %}
<span upvote-id = "{{ article.id }}">{{ total_upvotes }}</span><span> upvote{{ total_votes|pluralize}}</span>
<span downvote-id = "{{ article.id }}">{{ total_downvotes }}</span><span> downvote{{ total_votes|pluralize}}</span>
{% endwith %}
</div>
<form method = 'post' action = '{% url "news:news_list" %}' form-id = '{{ article.id }}' class="form">
{{ form.as_p }}
{% csrf_token %}
<input type = "submit" value = "post">
</form>
{% endfor %}
</div>
{% endblock %}
{% block domready %}
const
list = document.getElementById('list'),
items = document.getElementsByClassName('vote');
forms = document.getElementsByClassName('form');
list.addEventListener('click', voteFunc);
list.addEventListener('submit', commentFunc);
function commentFunc(event){
event.preventDefault();
const clickedForm = event.target;
console.log('event triggered');
for (let form in forms){
if (form == clickedForm){
console.log('form is event.target')
$.ajax({
url: '{% url "news:news_list" %}',
type: 'POST',
data: {'id':$(event.target).attr('form-id'), 'title':$(this).elemets['title_field'].text(), 'body':$(this).elemets['body_field'].text()},
dataType: 'json'
})
}
}
}
Hope to hear advice how to implement it better and what event.target contains
You can write event handler for form submit event .So, whenever submit button(post) is clicked this event will get called then use .serialize() method to get all inputs inside your form and also attach form-id using &name=value and then you can pass same to backend.
Demo Code :
//when form will get submit
$("form.form").submit(function(e) {
//serialize will get all inputs as name=value separted wth `& `
console.log("data to send --> " + $(this).serialize() + "&id=" + $(this).attr('form-id'))
$.ajax({
type: "POST",
url: '{% url "news:news_list" %}',
data: $(this).serialize() + "&id=" + $(this).attr('form-id'), //send same
dataType: 'json'
});
e.preventDefault();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<a href="{{ article.resource }}">
<h1>A1</h1>
</a>
<p>abcd..</p>
<img src="{{ article.url }}">
<p>
<button>Upvote</button>
<button>Downvote</button>
</p>
<div id="span">
<span upvote-id="1">23</span><span> 54</span>
<span downvote-id="1">2</span><span> 56</span>
</div>
<form method='post' action='{% url "news:news_list" %}' form-id='1' class="form">
<p><label>somehting:</label>
<input type="text" name="something"></p>
<input type="submit" value="post">
</form>
<a href="{{ article.resource }}">
<h1>A</h1>
</a>
<p>abcd..</p>
<img src="{{ article.url }}">
<p>
<button>Upvote</button>
<button>Downvote</button>
</p>
<div id="span">
<span upvote-id="2">23</span><span> 54</span>
<span downvote-id="2">2</span><span> 56</span>
</div>
<form method='post' action='{% url "news:news_list" %}' form-id='2' class="form">
<p><label>somehting:</label>
<input type="text" name="something"></p>
<input type="submit" value="post">
</form>
</div>

AJAX POST not actually sending POST data with Django

I want to submit a form to my Django back end using an AJAX post. I have multiple forms on the page but only want the one the user submits to be the one that sends.
The form is held in a modal:
<div class="modal-body">
<div class='content-section'>
<form method="POST" id="form{{ prod.id }}" class="showform" value="{{ prod.id }}" >
<input type="hidden" value="{{ prod.id }}" name="prodid">
{% csrf_token %}
<fieldset class='form-group'>
{{ form|crispy}}
</fieldset>
</form>
</div>
</div>
<div class="modal-footer">
<div class='form-group'>
<button class="btn btn-outline-info submit-form" value={{prod.id}} form="form{{ prod.id }}"
>Save
To Profile</button>
</div>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
When the submit button is pressed, it triggers the following AJAX :
$(document).on('click', '.submit-form', function () {
var thisButton = $(this)[0]
var prodID = $(this).val();
var form = $("form" + prodID);
$.ajax({
type: 'post',
headers:{
"X-CSRFToken": '{{ csrf_token }}'
},
url: '/ajax/validate_showadd/',
dataType: 'json',
contentType: 'json',
data: {
'form': form.serialize(),
"prodID":prodID,
},
success: function (data) {
console.log("sent")
},
error: function(data) {
console.log("error")
}
});
return false;
});
However, within Django whenever I try access any of these values it just returns 'None' and the QueryDict for the POST request is empty.
Thank you

AJAX update list of object

Can someone help me and say whats wrong I did?
In my django project I have product_detail page which has comment part. I am tring to update comments list after successfully adding new comment with AJAX. Unfortunatly it updates all page. I am little bit comfused and need advice. I need to update only list of comments not all page.
product_detail.html:
<div class="card">
<div class="card-block">
<table id="comment-table">
<thead>
<tr>
<th>Author</th>
<th>Date</th>
<th>Comment Text</th>
</tr>
</thead>
<tbody>
{% include 'project/comment_list.html' %}
</tbody>
</table>
</div>
<div class="card-footer">
<form method="post" class="comment-form" id="comment-form" action="{% url 'project:comment_add' project_code=project.code product_code=product.code %}">
{% csrf_token %}
{% for field in form %}
<div class="form-group{% if field.errors %} has-error{% endif %}">
{% render_field field class="form-control" %}
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Send</button>
</form>
</div>
</div>
views.py:
def comment_add(request, project_code, product_code):
data = dict()
project = get_object_or_404(Project, pk=project_code, status='open')
product = get_object_or_404(Product, pk=product_code)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.author = request.user
comment.save()
product.comments.add(comment)
data['form_is_valid'] = True
data['html_comment'] = render_to_string('project/comment_list.html', {'product': product})
form = CommentForm()
else:
data['form_is_valid'] = False
else:
form = CommentForm()
context = {'project': project, 'product': product, 'form': form}
return render(request, 'project/product_detail.html', context)
js:
$(function () {
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#comment-table tbody").html(data.html_comment);
}
else {
$("#comment-form").html(data.html_comment_form);
}
}
});
return false;
};
$("#comment-form").on("submit", ".comment-form", saveForm);
});
The problem is type="submit" native refresh new page. You have to stop form submitting. Try something like this:
$("#comment-form").submit(function(event) {
/* stop form from submitting normally */
event.preventDefault();
// here your ajax code
});

Categories