Update only one element inside same div classes using jQuery - javascript

I am trying to update the DOM, whenever a user likes a post and displays the number of likes on a post. However, I realized my function will update all the classes on the pages and not only the certain post being liked (When a user clicks on thmbs up, all the thumbs up buttons change to dumbs down)
my function for changing the like:
function like_post() {
// newly added
$('#like-section #likeBtn').on("click", function (e) {
e.preventDefault();
if($("#like-section #likeBtn i").hasClass("fa-thumbs-up")){
($("#like-section #likeBtn i").removeClass("fa-thumbs-up"))
($("#like-section #likeBtn i").addClass("fa-thumbs-down"))
} else {
($("#like-section #likeBtn i").removeClass("fa-thumbs-down"))
($("#like-section #likeBtn i").addClass("fa-thumbs-up"))
}
});
// end
}
my posts HTML template in Django:
{% load static %}
<link rel="stylesheet" href="{% static 'css/post/style.css' %}">
<script src="{% static 'js/like-api.js' %}"></script>
<script src="{% static 'js/post.js' %}"></script>
{% for post in posts %}
<script>
$(document).on('click', '.post-detail-clickable-details-view', function () {
var url = $(this).attr("data-url")
document.location.href = url
});
</script>
<div class="row ml-2">
<div class="col-sm-2">
<div class="float-right mb-3 mt-3">
<div>
<img class="img-create-post rounded-circle mr-2" src="https://mdbootstrap.com/img/Photos/Avatars/avatar-5.jpg"
alt="Profile image">
</div>
<div>
<p class="text-muted post-card-date small mr-2">{{ post.get_created_on }} ago</p>
</div>
</div>
</div>
<div class="col-md-10" style="margin-left: -1.6rem;">
<div class="card rounded-0 mb-3 mt-3">
<div class="card-header bg-transparent" style="height: 3rem;">
<h5 style="margin-bottom: 0px;">
<a class="text-dark" style="text-decoration: none;" href="{% url 'home:post-detail' post.guid_url %}">{{ post.title }}</a>
<span class="small text-muted">#{{ post.author.username }}</span>
</h5>
</div>
<div class="card-body post-detail-clickable-details-view text-dark" data-url="{% url 'home:post-detail' post.guid_url %}"
style="margin-top:-0.5rem;">
<a id="post-detail-view-link" href="{% url 'home:post-detail' post.guid_url %}"></a>
<p class="mr-1 text-dark font-weight-bolder">{{ post.author.first_name }} {{ post.author.last_name }}</p>
<p class="card-text pt-2" style="margin-top: -0.9rem;">{{ post.content }}</p>
</div>
<hr style="margin: 0;">
<div class="d-flex align-items-center justify-content-between" >
<div class="row mx-1">
<div id="like-section" class="px-1">
{% include 'home/posts/likes.html' with post=post %}
</div>
<div class="px-1">
<a class="btn btn-md" href="{% url 'home:post-detail' post.guid_url %}">
<span class="text-secondary">
<i class="fas fa-comment"></i> {{ post.comments.count }}
</span>
</a>
</div>
</div>
<div>
<a class="btn btn-md" href="#">
<span class="text-secondary">
<i class="fas fa-share-square"></i>
</span>
</a>
</div>
</div>
</div>
</div>
</div>
{% empty %}
<div class="d-flex justify-content-center">
<h5 class="h5 font-weight-lighter my-3 text-muted">No posts to show</h5>
</div>
{% endfor %}
my likes.html:
{% load static %}
<!-- static file were here -->
{% if request.user.is_authenticated %}
<script src="{% static 'js/post.js' %}"></script>
<script src="{% static 'js/comment.js' %}"></script>
<form action="{% url 'home:post-like' post.id %}" method="POST">
{% csrf_token %}
{% if request.user in post.likes.all or is_liked %}
<button type="submit" id="likeBtn" data-url="{% url 'home:post-like' post.guid_url %}" data-token="{{ csrf_token }}" name="post_id" value="{{ post.id }}" class="btn btn-md">
<span class="text-secondary">
<i class="fas fa-thumbs-down"></i>
<span id="like-count">
{{ post.likes.count }}
</span>
<input type="hidden" id="input-like-count" value=" {{ post.likes.count }} " />
</span>
</button>
{% else %}
<button type="submit" id="likeBtn" data-url="{% url 'home:post-like' post.guid_url %}" data-token="{{ csrf_token }}" name="post_id" value="{{ post.id }}" class="btn btn-md">
<span class="text-secondary">
<i class="fas fa-thumbs-up"></i>
<span id="like-count">
{{ post.likes.count }}
</span>
<input type="hidden" id="input-like-count" value=" {{ post.likes.count }} " />
</span>
</button>
{% endif %}
</form>
<div class="modal fade" id="modal-post-detail">
<div class="modal-dialog modal-dialog-scrollable modal-md adjusted-modal-detail">
<div class="modal-content"></div>
</div>
</div>
{% endif %}
my plan is to change the display for a user so there is no need to refresh the page and update the number of counts as well before refreshing the page. But currently, all the #likeBtn elements are being updated and not the one for the single post. How can I update the button of the post being liked only?
EDIT: I updated my jQuery to this, and it's still not working:
$('#like-section #likeBtn').on("click", function (e) {
e.preventDefault();
if($(this).find("#i").hasClass("fa-thumbs-up")){
($(this).find("i").removeClass("fa-thumbs-up").addClass("fa-thumbs-down"))
} else {
($(this).find("i").removeClass("fa-thumbs-down").addClass("fa-thumbs-up"))
}
});
EDIT: jsfiddle link: https://jsfiddle.net/mf0xvpho/1/
This seems to be working now

Consider the following example.
Fiddle: https://jsfiddle.net/Twisty/2hg60be3/13/
HTML
<div class="like-section">
<button type="submit" class="likeBtn btn btn-md">
<span class="text-secondary">
<i class="red">Button</i>
<span class="like-count">
3
</span>
</span>
</button>
</div>
<div class="like-section">
<button type="submit" class="likeBtn btn btn-md">
<span class="text-secondary">
<i class="blue">Button</i>
<span class="like-count">
2
</span>
</span>
</button>
</div>
<div class="like-section">
<button type="submit" id="likeBtn" class="btn btn-md">
<span class="text-secondary">
<i class="red">Button</i>
<span class="like-count">
1
</span>
</span>
</button>
</div>
JavaScript
$(function() {
$('.like-section').on("click", ".likeBtn", function(e) {
var like_count = parseInt($(".like-count", this).text());
e.preventDefault();
if ($("i", this).hasClass("blue")) {
like_count++;
$("i", this).removeClass("blue").addClass("red");
$(".like-count", this).text(like_count);
} else {
like_count--;
$("i", this).removeClass("red").addClass("blue");
$(".like-count", this).text(like_count);
}
});
});
Using classes will allow you to group elements. You can use .find() or shorthand, $("i", this). It's the same as $(this).find("i"), just shorter.

Related

javascript querySelectorAll is not working on all django objects in the template

I'm working on Auctions website using Javascript and Django. I want to make each user has the ability to view products that he has participated in whether by selling , competition by bids or won bids. So I created a page containing three buttons(won, selling , competiting). On clicking on each buttons , shows the related products(change the display on click). Until now it works. The problem that I want in each product card on mouse over it shows certain div and on mouse out it shows another div. I created the functionality using Javascript (by forEach card in query that selects all cards). the problem that this functionality works on certain cards but upon clicking on the buttons that shows won or competition products, it doesn't work on the related cards (not working on all cards).
html:
<div class="container">
<div id="userbidsbuttons">
<button class='userbidsbu'id="viewsell">Posted</button>
<button class='userbidsbu'id="viewbuy">Won</button>
<button class='userbidsbu'id="viewnow">In competition</button>
</div>
<div class="indexobj">
<div id="viewselluser">
{% if yy.0 is not None%}
{% for obj in yy %}
<div class="card {{obj.bidcategory}}" style="width: 18rem;" id="{{obj.id}}">
<img class="card-img-top" src="..{{obj.image.url}}" alt="Card image cap">
<div class="thecardcontent" id="co{{obj.id}}">
<div class="card-body">
<h5 class="card-title">{{obj.name}}</h5>
<p class="card-text">{{obj.bidcategory.category}}</p>
</div>
<ul class="list-group list-group-flush">
<ul class="list-group-item"><li ><i class="fa-solid fa-car"></i> {{obj.model}}</li>
<li ><i class="fa-solid fa-star"></i> {{obj.brand}}</li></ul>
<ul class="list-group-item"><li ><i class="fa-solid fa-user"></i> {{obj.bidseller}}</li>
<li > <i class="fa-solid fa-location-dot"></i> {{obj.bidstate.state}}</li></ul>
<ul class="list-group-item">
<li ><i class="fa-solid fa-money-bill"></i> <span id="p{{obj.id}}">{{obj.hightestbid.bid}}</span>$</li>
<li class='timer'id="{{obj.id}}"><i class="fa-regular fa-clock"></i>{{obj.difference}}</li>
</ul>
</ul>
</div>
<div class="thecardbutton" id="bu{{obj.id}}">
<div class="list-group-item currbi" ><i class="fa-solid fa-money-bill"></i> Current bid:<span id="p{{obj.id}}">{{obj.hightestbid.bid}}</span>$</div>
<div class="card-body">
viewbid</button>
</div>
<div>
<form class="indexaddbid" id="{{obj.id}}">
{% csrf_token %}
<input type="number" placeholder="Add bid" id="s{{obj.id}}" class="indexinput">
</form>
<button class="viewbid onedollar" id="{{obj.id}}">Add 1$</button>
</div>
</div>
</div>
{% endfor %}
{% else %}
<h1>No Selled bids</h1>
{% endif %}
</div>
<div id="userbidsbuy">
{% if xx.0 is not None%}
{% for obj in xx %}
{% if obj.selling == False %}
<div class="card {{obj.bidcategory}}" style="width: 18rem;" id="{{obj.id}}">
<img class="card-img-top" src="..{{obj.image.url}}" alt="Card image cap">
<div class="thecardcontent" id="co{{obj.id}}">
<div class="card-body">
<h5 class="card-title">{{obj.name}}</h5>
<p class="card-text">{{obj.bidcategory.category}}</p>
</div>
<ul class="list-group list-group-flush">
<ul class="list-group-item"><li ><i class="fa-solid fa-car"></i> {{obj.model}}</li>
<li ><i class="fa-solid fa-star"></i> {{obj.brand}}</li></ul>
<ul class="list-group-item"><li ><i class="fa-solid fa-user"></i> {{obj.bidseller}}</li>
<li > <i class="fa-solid fa-location-dot"></i> {{obj.bidstate.state}}</li></ul>
<ul class="list-group-item">
<li ><i class="fa-solid fa-money-bill"></i> <span id="p{{obj.id}}">{{obj.hightestbid.bid}}</span>$</li>
<li class='timer'id="{{obj.id}}"><i class="fa-regular fa-clock"></i>{{obj.difference}}</li>
</ul>
</ul>
</div>
<div class="thecardbutton" id="bu{{obj.id}}">
<div class="list-group-item currbi" ><i class="fa-solid fa-money-bill"></i> Current bid:<span id="p{{obj.id}}">{{obj.hightestbid.bid}}</span>$</div>
<div class="card-body">
viewbid</button>
</div>
<div>
<form class="indexaddbid" id="{{obj.id}}">
{% csrf_token %}
<input type="number" placeholder="Add bid" id="s{{obj.id}}" class="indexinput">
</form>
<button class="viewbid onedollar" id="{{obj.id}}">Add 1$</button>
</div>
</div>
</div>
{% endif %}
{% endfor %}
{% else %}
<h1>No won bids</h1>
{% endif %}
</div>
<div id="userbidsnow">
{% if zz.0 is not None%}
{% for obj in zz %}
{% if obj.pending == True %}
<div class="card {{obj.bidcategory}}" style="width: 18rem;" id="{{obj.id}}">
<img class="card-img-top" src="..{{obj.image.url}}" alt="Card image cap">
<div class="thecardcontent" id="co{{obj.id}}">
<div class="card-body">
<h5 class="card-title">{{obj.name}}</h5>
<p class="card-text">{{obj.bidcategory.category}}</p>
</div>
<ul class="list-group list-group-flush">
<ul class="list-group-item"><li ><i class="fa-solid fa-car"></i> {{obj.model}}</li>
<li ><i class="fa-solid fa-star"></i> {{obj.brand}}</li></ul>
<ul class="list-group-item"><li ><i class="fa-solid fa-user"></i> {{obj.bidseller}}</li>
<li > <i class="fa-solid fa-location-dot"></i> {{obj.bidstate.state}}</li></ul>
<ul class="list-group-item">
<li ><i class="fa-solid fa-money-bill"></i> <span id="p{{obj.id}}">{{obj.hightestbid.bid}}</span>$</li>
<li class='timer'id="{{obj.id}}"><i class="fa-regular fa-clock"></i>{{obj.difference}}</li>
</ul>
</ul>
</div>
<div class="thecardbutton" id="bu{{obj.id}}">
<div class="list-group-item currbi" ><i class="fa-solid fa-money-bill"></i> Current bid:<span id="p{{obj.id}}">{{obj.hightestbid.bid}}</span>$</div>
<div class="card-body">
viewbid</button>
</div>
<div>
<form class="indexaddbid" id="{{obj.id}}">
{% csrf_token %}
<input type="number" placeholder="Add bid" id="s{{obj.id}}" class="indexinput">
</form>
<button class="viewbid onedollar" id="{{obj.id}}">Add 1$</button>
</div>
</div>
</div>
{% endif %}
{% endfor %}
{% else %}
<h1>No won bids</h1>
{% endif %}
</div>
</div>
javascript:
document.addEventListener('DOMContentLoaded',function(){
document.querySelectorAll('.card').forEach(card => {
card.addEventListener('mouseover', function(){
document.getElementById(`co${card.id}`).style.display = 'none';
document.getElementById(`bu${card.id}`).style.display = 'block';
})
card.addEventListener('mouseout', function(){
document.getElementById(`co${card.id}`).style.display = 'block';
document.getElementById(`bu${card.id}`).style.display = 'none';
})
})
document.querySelector('#viewbuy').addEventListener('click',function(){
document.querySelector('#userbidsbuy').style.display ='flex';
document.querySelector('#viewselluser').style.display='none';
document.querySelector('#userbidsnow').style.display='none';
})
document.querySelector('#viewsell').addEventListener('click',function(){
document.querySelector('#userbidsbuy').style.display ='none';
document.querySelector('#viewselluser').style.display='flex';
document.querySelector('#userbidsnow').style.display='none';
})
document.querySelector('#viewnow').addEventListener('click',function(){
document.querySelector('#userbidsbuy').style.display ='none';
document.querySelector('#viewselluser').style.display='none';
document.querySelector('#userbidsnow').style.display='flex';
})
})
console.log('wor')
css:
#userbidsnow{
display: none;
}
#userbidsbuy{
display: none;
}
, so how can I solve it
I tried to solve it with using load event listener but not working

In Django bootstrap project toast messages showing for the first card in loop element

I want to toast messages for all those cards. but it is showing for the first card only. I have attached a view of my page where I want to add a toast message to view the details of the card if a user is not logged in.
I noob in Django and Javascript. this is a small part of my university project.
my page looks like this: https://i.stack.imgur.com/cYSPW.jpg
document.getElementById("toastbtn").onclick = function() {
var toastElList = [].slice.call(document.querySelectorAll('.toast'))
var toastList = toastElList.map(function(toastEl) {
return new bootstrap.Toast(toastEl)
})
toastList.forEach(toast => toast.show())
}
<section class="details-card">
<div class="container">
<div class="row">
{% for homes in home %}
<div class="col-md-4 mb-4">
<div class="card-content">
<div class="card-img">
<img src="{{ homes.coverImg.url }}" alt="Cover Image">
<span><h4>{{ homes.pricePerMonth }}Taka</h4></span>
</div>
<div class="card-desc">
<p class="small mb-1"> <i class="fas fa-map-marker-alt mr-2"></i>{{homes.address}}</p>
<h3>{{ homes.title}}</h3>
{% if request.user.is_authenticated %}
Details
{% else %}
<button type="button" class="btn btn-primary" id="toastbtn">XDetails</button>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</section>
<!-- Alert Message Popup-->
<!--bottom-0 end-0 p-3-->
<div class="position-fixed top-50 start-50 translate-middle p-3" style="z-index: 11">
<div id="liveToast" class="toast hide" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<img src="({% static 'img/icon.png' %})" class="rounded me-2" alt="...">
<strong class="me-auto">My Second Home</strong>
<small>0.1s ago</small>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Hello!<br>You need to login first to see details.
<div class="mt-2 pt-2 border-top">
<a class="btn btn-primary btn-sm" href="{% url 'login' %}">Sign In</a>
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="toast">Close</button>
</div>
</div>
</div>
So here your problem comes from the id toastbtn. You have iterated the for loop and all the buttons in the cards got the same id but id unique for everyone so the id is added to the first card button only. Here one thing can be done remove the toastbtn id from the button and onclick attribute on the btn and pass the value the function call like shown below -
<button type="button" class="btn btn-primary" onclick="showToast()">XDetails</button>
The showToast function is the same function u added in you js file
Your JS file will look like this
function showToast() {
var toastElList = [].slice.call(document.querySelectorAll('.toast'))
var toastList = toastElList.map(function(toastEl) {
return new bootstrap.Toast(toastEl)
})
toastList.forEach(toast => toast.show())
}
HTML File
<section class="details-card">
<div class="container">
<div class="row">
{% for homes in home %}
<div class="col-md-4 mb-4">
<div class="card-content">
<div class="card-img">
<img src="{{ homes.coverImg.url }}" alt="Cover Image">
<span><h4>{{ homes.pricePerMonth }}Taka</h4></span>
</div>
<div class="card-desc">
<p class="small mb-1"> <i class="fas fa-map-marker-alt mr-2"></i>{{homes.address}}</p>
<h3>{{ homes.title}}</h3>
{% if request.user.is_authenticated %}
Details
{% else %}
<button type="button" class="btn btn-primary" onclick="showToast()">XDetails</button>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</section>
<!-- Alert Message Popup-->
<!--bottom-0 end-0 p-3-->
<div class="position-fixed top-50 start-50 translate-middle p-3" style="z-index: 11">
<div id="liveToast" class="toast hide" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<img src="({% static 'img/icon.png' %})" class="rounded me-2" alt="...">
<strong class="me-auto">My Second Home</strong>
<small>0.1s ago</small>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Hello!<br>You need to login first to see details.
<div class="mt-2 pt-2 border-top">
<a class="btn btn-primary btn-sm" href="{% url 'login' %}">Sign In</a>
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="toast">Close</button>
</div>
</div>
</div>

Cant figure out infinite scrolling with Waypoints

Trying to apply infinite scrolling using Waypoints but cant seem to get it working.
I have the following scripts loaded in my base.html after downloading them and saving in my static folder:
<script src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
<script src="{% static 'js/jquery.waypoints.min.js' %}"></script>
<script src="{% static 'js/infinite.min.js' %}"></script>
Then I have the following code in my template exteded from the base:
{% extends "base.html" %}
{% load static %}
{% block css %}
<link rel="stylesheet" href="{% static 'home/main.css' %}">
{% endblock css %}
{% block content %}
<br>
<div class="container status-update">
<div class="container">
<form>
<div class="input-group-lg">
<input type="text" class="form-control" value="What's new?">
</div>
<br style="height:20px">
<button type="submit" class="btn btn-primary btn-lg" name="button">Post</button>
</form>
</div>
</div>
<br>
<div class="container">
<nav class="navbar navbar-expand-lg navbar-light" style="background-color: #6298bf">
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<div class="navbar-nav">
<a class="nav-link active" href="{% url 'home' %}">Activity Feed</a>
<a class="nav-link" href="{% url 'vehicle_updates' %}">Vehicle Updates<span class="sr-only">(current)</span></a>
<a class="nav-link" href="/space.html">Garage Updates</a>
</div>
</div>
</nav>
</div>
<br>
<div class="container">
<div class="primary-segments">
<h2>Activity Updates</h2>
<div class="infinite-container">
{% for post in posts %}
<div class="infinite-item">
<div class="card m-3">
<div class="card-body" style="background-color:#bdcade; padding-bottom:0px">
<div class="media mb-3">
<img src="{{ user.profile.image.url }}" class="d-block ui-w-40 rounded-circle" style="width:40px;height:auto;" alt="">
<div class="media-body ml-3">
<h5 style="color:#ffffff">{{ post.user.first_name }} {{ post.user.last_name }}</h5>
<div class="small text-muted">Yesterday</div>
</div>
</div>
</div>
{% if post.image %}
<img src="{{ post.image.url }}" class="card-img-top" alt="">
{% endif %}
<div class="card-body">
<h5 class="card-title">{{ post.title }}</h5>
<p class="card-text">{{ post.content }}</p>
<div class="btn-group" role="group">
<button type="button" class="btn btn-secondary">Like</button>
<button type="button" class="btn btn-secondary">Comment</button>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% if page_obj.has_next %}
<a class="infinite-more-link" href="?page={{ page_obj.next_page_number }}">More</a>
{% endif %}
</div>
</div>
<script type="javascript">
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0]
});
</script>
{% endblock content %}
When I run the server and load the page, it just shows a `more' button at the bottom of the page that I can click on to take me to the next group of objects (set pagination to 3 in the view).
Doesn't look like it is throwing any errors in the console when I run the server, so I'm not sure where to look next for the problem. Any help would be much appreciated.
Figured it out.
Moved the the JS script tags from the bottom of the body up into the head and it started working. Wasn't aware of this location dependency.

Django submit button not working on Ajax request

I am building a website which users can create posts and comment on it, however, after clicking the submit button in the post_detail.html template to submit the comment, nothing happens and I cannot een see an error. I am using jQuery to submit the form
this is my post_detail view:
#login_required
def post_detail(request, id):
data = dict()
post = get_object_or_404(Post, id=id)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(False)
comment.post = post
comment.name = request.user
comment.save()
comments = post.comments.all()
data['form_is_valid'] = True
data['comments'] = render_to_string('home/posts/post_detail.html', { 'comments':comments }, request=request)
else:
data['form_is_valid'] = False
else:
form = CommentForm
comments = post.comments.all()
context = {
'form': form,
'comments': comments,
'post': post
}
data['html_data'] = render_to_string('home/posts/post_detail.html', context,request=request)
return JsonResponse(data)
this is my post_detail.html template:
{% load crispy_forms_tags %}
{% load static %}
<script src="{% static 'js/comment.js' %}"></script>
<div class="modal-header-sm">
<button type="button" class="close mx-2" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="card mt-3 rounded-0 mb-3" style="max-width: 100rem !important;">
<div class="card-body text-dark">
<div class="d-flex">
<img class="img-create-post rounded-circle mr-2" style="width: 50px;height: 50px;" src="https://mdbootstrap.com/img/Photos/Avatars/avatar-5.jpg"
alt="Profile image">
<span class="align-text-top"><a class="mr-2 text-dark font-weight-bolder" href="#">{{ post.author.first_name }} {{ post.author.last_name }} </a><br><p class="font-weight-light text-muted">{{ post.title }}</p></span>
<div class="float-right text-right ml-auto">
<p class="text-muted small" style="font-size: 0.7rem;">{{ post.date_posted|date:"F d, Y" }}</p>
</div>
</div>
<p class="card-text">{{ post.content }}</p>
</div>
<div class="card-footer" style="height: 5rem;">
<a class="mx-1 small" data-href='{{ post.get_api_like_url }}' data-likes='{{ post.likes.count }}' href='{{ post.get_like_url }}'><i class="fas fa-thumbs-up"></i> Like</a>
<hr class="my-1">
<p class="text-muted small">
{% if post.author == request.user %}
<button class="btn btn-sm text-muted show-form-delete ml-auto" data-url="{% url 'home:post-delete' post.id %}" style="font-size: small;" style="height: 0rem;">Remove</button>
{% endif %}
<small class="float-sm-right">
{{ post.likes.count }} Likes, {{ post.comments.count }} Comments
</small>
</p>
</div>
<div class="card-body">
<div class="row">
<img class="img-create-post rounded-circle mr-2" style="width: 40px;height: 40px;" src="{{ request.user.image }}" alt="Profile image">
<form method="POST" data-url="{% url 'home:post-detail' post.id %}" class="post-comment-form">
{% csrf_token %}
<div class="row ml-1">
{{ form | crispy }}
<button class="btn btn-sm ml-1 small btn-rounded btn-primary" style="height: 2.3rem;" type="submit">Add</button>
</div>
</form>
</div>
<hr>
</div>
<div id="post-linked-comments">
<div>
{% include 'home/posts/post_comment.html' %}
</div>
</div>
</div>
the post_comment.html template for your reference however it is most likely not the issue:
<ul class="list-group list-group-flush">
{% for comment in comments %}
<li class="list-group-item">
<div class="d-flex">
<img class="img-create-post rounded-circle mr-1" style="width: 20px;height: 20px;" src="{{ comment.name.image }}"
alt="Profile image">
<span class="align-text-top font-weight-bolder">{{ comment.name.first_name }}
<p class="text-muted small mx-2" style="font-size: 0.7rem;">{{ comment.created_on|date:"F d, Y at: f A" }}</p><br>
<p class="font-weight-light">{{ comment.body }}</p></span>
</div>
</li>
{% empty %}
<li class="list-group-item">
<div class="d-flex">
<p class="font-weight-lighter text-muted">No comments to show</p>
</div>
</li>
{% endfor %}
</ul>
and finally my javascript code in comment.js:
$(document).ready(function(){
var ShowForm = function(e){
e.stopImmediatePropagation();
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType:'json',
beforeSend: function(){
$('#modal-post-detail').modal('show');
},
success: function(data){
$('#modal-post-detail .modal-content').html(data.html_data);
}
});
};
var SaveForm = function(e){
e.stopImmediatePropagation();
var form = $(this);
$.ajax({
url: form.attr('data-url'),
data: form.serialize(),
type: form.attr('method'),
dataType: 'json',
success: function(data){
if(data.form_is_valid){
$('#post-linked-comments div').html(data.comments);
alert('Comment added')
} else {
$('#modal-post-detail .modal-content').html(data.html_data)
}
}
})
return false;
}
//adding a comment
$('.comment-post-btn').click(ShowForm);
$('.post-detail-clickable-details-view').click(ShowForm);
$('#modal-post-detail').on("submit",".post-comment-form",SaveForm)
});
There is no issue with getting the Javascript file as the post_detail modal pops up fine, however after clicking on the add button nothing happens.
Thanks for all the help in advance.
EDIT: Button should be added inside the form but now NoReverseMatchException is being thrown after clicking on 'Add' button:
New Form:
<form method="POST" data-url="{% url 'home:post-detail' post.id %}" class="post-comment-form">
{% csrf_token %}
<div class="row ml-1">
{{ form | crispy }}
<button class="btn btn-sm ml-1 small btn-rounded btn-primary" style="height: 2.3rem;" type="submit">Add</button>
</div>
</form>
urls.py:
path('post/<int:id>/', views.post_detail, name='post-detail'),
Error:
django.urls.exceptions.NoReverseMatch: Reverse for 'post-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['home/post/(?P<id>[0-9]+)/$']
SOLVED: I managed to solve the issue myself. it was from my views. I was sending the comments to the wrong html template. Below you can see the corrected view for the template.
#login_required
def post_detail(request, id):
data = dict()
post = get_object_or_404(Post, id=id)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(False)
comment.post = post
comment.name = request.user
comment.save()
comments = post.comments.all()
data['form_is_valid'] = True
#data['comments'] = render_to_string('home/posts/post_detail.html', { 'comments':comments }, request=request)
#corrected code below
data['comments'] = render_to_string('home/posts/post_comment.html', { 'comments':comments }, request=request) else:
data['form_is_valid'] = False
else:
form = CommentForm
comments = post.comments.all()
context = {
'form': form,
'comments': comments,
'post': post
}
data['html_data'] = render_to_string('home/posts/post_detail.html', context,request=request)
return JsonResponse(data)
I believe nothing is happening since the submit button is not defined within any form tags.
From the code in post_detail.html the button tags are outside the form tags.
<div class="row">
<img class="img-create-post rounded-circle mr-2" style="width: 40px;height: 40px;" src="{{ request.user.image }}" alt="Profile image">
<form method="POST" data-url="{% url 'home:post-detail' post.id %}" class="post-comment-form">
{% csrf_token %}
<div class="moda-body">
{{ form | crispy }}
</div>
</form>
<button class="btn btn-sm ml-1 small btn-rounded btn-primary" style="height: 2.3rem;" type="submit">Add</button>
</div>
The button tag should be placed before the closing tag of the form.
<div class="row">
<img class="img-create-post rounded-circle mr-2" style="width: 40px;height: 40px;" src="{{ request.user.image }}" alt="Profile image">
<form method="POST" data-url="{% url 'home:post-detail' post.id %}" class="post-comment-form">
{% csrf_token %}
<div class="moda-body">
{{ form | crispy }}
</div>
<button class="btn btn-sm ml-1 small btn-rounded btn-primary" style="height: 2.3rem;" type="submit">Add</button>
</form>
</div>

Bootstrap radio button isn't working in flask

I am using Bootstrap 4 radio button radio button in a flask application. and below is the snippet I used
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-outline-secondary">
<input type="radio" onclick="javascript:toggleElements();" name="toggle" id="twitter"/> Twitter
</label>
<label class="btn btn-outline-secondary" >
<input type="radio" onclick="javascript:toggleElements();" name="toggle" id="facebook"/> Facebook
</label>
</div>
and the javascript code
<script type="text/javascript">
function toggleElements() {
alert('hurray');
if(document.getElementBId('twitter').checked) {
document.getElementById('twitterrows').style.display = 'block';
document.getElementById('facebookrows').style.display = 'none';
}
if(document.getElementById('facebook').checked) {
document.getElementById('facebookrows').style.display = 'block';
document.getElementById('twitterrows').style.display = 'none';
}
}
</script>
Initially,I tried with simple html radio buttons and was able to trigger Javascript function toggleElements(). However, after replacing the normal radio buttons with the bootstrap radio, nothing is triggered.
Below is the entire html code
{% from 'helper/forms.html' import render_field with context %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sharjah Tourism Search Results</title>
<script src="{{ url_for('static', filename='js/jquery-3.2.1.min.js') }}"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="{{ url_for('static',filename='styles/home.css')}}"/>
<script type="text/javascript">
function toggleElements() {
alert('hurray');
if(document.getElementBId('twitter').checked) {
document.getElementById('twitterrows').style.display = 'block';
document.getElementById('facebookrows').style.display = 'none';
}
if(document.getElementById('facebook').checked) {
document.getElementById('facebookrows').style.display = 'block';
document.getElementById('twitterrows').style.display = 'none';
}
}
</script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="{{ url_for('home')}}"><strong>Search</strong></a>
<button class = "navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent-7"
aria-controls="navbarSupportedContent-7" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent-7">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="{{url_for('add_url')}}">Add<span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('file_render')}}">Import</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbardrop" data-toggle="dropdown">
Websites
</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="{{ url_for('list_urls') }}">List</a>
<a class="dropdown-item" href="{{ url_for('list_crawled_websites')}}">Selected</a>
</div>
</li>
</ul>
</div>
</nav>
<!-- Header -->
<div class="container">
<br />
<div class="row">
<!-- Logo -->
<div class="col-sm">
<img class="w-50 h-60" src="{{url_for('static',filename='images/sctda_logo.jpg')}}" />
</div>
<!-- Search Bar -->
<div class="col-sm-5 searchbar">
<form action="{{url_for('fetch_results')}}" method="POST">
<div class="input-group">
<input type="search" placeholder="Search" class="form-control" name="search" id="search" value="{{data['search_term']}}" class="w-75 h-75" required>
<div class="input-group-append">
<button type="submit" class="btn btn-outline-secondary btn-sm"><i class="fa fa-search"></i></button>
</div>
</div>
</form>
</div>
</div>
<div id="container">
<div class="row">
{%set data = data['results'] %}
<div class="col-md-4">
<div class="btn-group-toggle" data-toggle="buttons">
<label class="btn btn-outline-secondary active">
<input type="radio" checked autocomplete="off"> Internal
</label>
</div>
<hr>
{% set internals = data['internal'] %}
{% if internals is defined and internals|length %}
{% for internal in internals %}
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ internal['title'] }}</h5>
<p class="card-text">{{ internal['description'] }}</p>
{{ internal['title'] }}
</div>
</div>
<br/>
{% endfor %}
{% else %}
<div class="card">
<div class="card-body">
<h5 class="card-title">No Records Found</h5>
</div>
</div>
<br/>
{% endif %}
</div>
<div class="col-md-4">
{% set externals = data['external'] %}
{% if externals is defined and externals|length %}
<div class="btn-group-toggle" data-toggle="buttons">
<label class="btn btn-outline-secondary active">
<input type="radio" checked autocomplete="off"> External
</label>
</div>
<hr>
{% for external in externals %}
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ external['title'] }}</h5>
<p class="card-text">{{ external['description'] }}</p>
{{ external['title'] }}
</div>
</div>
<br/>
{% endfor %}
{% else %}
<div class="card">
<div class="card-body">
<h5 class="card-title">No Records Found</h5>
</div>
</div>
<br/>
{% endif %}
</div>
<div class="col-md-4">
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-outline-secondary">
<input type="radio" onclick="javascript:toggleElements();" name="toggle" id="twitter"/> Twitter
</label>
<label class="btn btn-outline-secondary" >
<input type="radio" onclick="javascript:toggleElements();" name="toggle" id="facebook"/> Facebook
</label>
</div>
<hr>
(<input type="radio" onclick="javascript:toggleElements();" name="toggle" id="twitter"/> Twitter,
<input type="radio" onclick="javascript:toggleElements();" name="toggle" id="facebook"/> Facebook)
<div id="twitterrows">
{% set tweets = data['twitter'] %}
{% if tweets is defined and tweets|length %}
{% for tweet in tweets %}
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ tweet['title'] }}</h5>
<p class="card-text">{{ tweet['description'] }}</p>
{{ tweet['title'] }}
</div>
</div>
<br/>
{% endfor %}
{% else %}
<div class="card">
<div class="card-body">
<h5 class="card-title">No Records Found</h5>
</div>
</div>
<br/>
{% endif %}
</div>
<div id="facebookrows">
{% set posts = data['facebook'] %}
{% if posts is defined and posts|length %}
{% for post in posts %}
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ post['title'] }}</h5>
<p class="card-text">{{ post['description'] }}</p>
{{ post['title'] }}
</div>
</div>
<br/>
{% endfor %}
{% else %}
<div class="card">
<div class="card-body">
<h5 class="card-title">No Records Found</h5>
</div>
</div>
<br/>
{% endif %}
</div>
</div>
</div>
</div>
<center>Developed by School of Information Technology Team,Skyline University College</center>
</body>
</html>
I strongly suspect with the order of scripts being called under the head tag. Can someone help me to fix this please.
make sure you have included the correct version of bootstrap. Please check if there is any error in the browser console.
https://getbootstrap.com/docs/4.4/components/input-group/#checkboxes-and-radios.
I am suspecting that the javascript click is not properly binded to the click event.
I fixed it by replacing the three script tags in the above html page with the below
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

Categories

Resources