Uncaught ReferenceError: (function = named as handleTweetActionBtn) is not defined at HTMLButtonElement.onclick
I have been trying to solve this error for quite some time now. The error in the console bar looks like this Console error image
I have been trying to develop my logic towards creating like and unlike button.
My index.html with script code looks like this
{% extends "network/layout.html" %}
{% block body %}
<div class="row text-center">
<div class="col">
<h2>Welcome to Network</h2>
</div>
</div>
<div class="row mb-3">
<div class="col-md-4 mx-auto col-10">
<form class="form" id="tweet-create-form" method="POST" action="/tweet-create">
{% csrf_token %}
<div class="d-none alert alert-danger" id="tweet-create-form-error">
</div>
<input type="hidden" value="/" name="next">
<textarea class="form-control" name="content" placeholder="What's happening?"></textarea>
<button type="submit" class="btn btn-primary col-12">TWEET</button>
</form>
</div>
</div>
<div class="row" id="tweets">
Replace me
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const tweetCreateFormEl = document.getElementById("tweet-create-form")
tweetCreateFormEl.addEventListener("submit", handleTweetCreateFormDidSubmit)
const tweetsContainerElement = document.getElementById("tweets")
//tweetsElement.innerHTML = "Loading..."
// Forms in JS
function handleTweetCreateFormDidSubmit(event){
event.preventDefault()
const myForm = event.target
const myFormData = new FormData(myForm)
const url = myForm.getAttribute("action")
const method = myForm.getAttribute("method")
const xhr = new XMLHttpRequest()
const responseType = "json"
xhr.responseType = responseType
xhr.open(method, url)
xhr.setRequestHeader("HTTP_X_REQUESTED_WITH", "XMLHttpRequest")
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
xhr.onload = function() {
if (xhr.status === 201){
handleTweetFormError("", false)
const newTwt = xhr.response
const newTweetElement = formatTweetElement(newTwt)
const ogHtml = tweetsContainerElement.innerHTML
tweetsContainerElement.innerHTML = newTweetElement + ogHtml
myForm.reset()
} else if (xhr.status === 401 || xhr.status === 403) {
alert("You must login!")
window.location.href = "/login"
} else {
const errorJson = xhr.response
const contentError = errorJson.content
let contentErrorMsg;
if (contentError){
contentErrorMsg = contentError[0]
if (contentErrorMsg) {
handleTweetFormError(contentErrorMsg, true)
}
else{
alert("An error occured. Please try again.")
}
}
alert("An error occured. Please try again.")
}
}
xhr.onerror = function() {
alert("An error occurred. Please try again later.")
}
xhr.send(myFormData)
}
//Form submission error handling
function handleTweetFormError(msg, display){
var myErrorDiv = document.getElementById("tweet-create-form-error")
if (display === true) {
// show error
myErrorDiv.setAttribute("class", "d-block alert alert-danger")
myErrorDiv.innerText = msg
} else {
// hide error
myErrorDiv.setAttribute("class", "d-none alert alert-danger")
}
}
//Loading Tweets list on Home
function loadTweets(tweetsElement) {
const xhr = new XMLHttpRequest()
const method = "GET"
const url = "/tweets"
const responseType = "json"
xhr.responseType = responseType
xhr.open(method, url) // Open request with prescribed method and url
xhr.onload = function() {
const serverResponse = xhr.response
const listedItems = serverResponse //array
var finalTweetStr = ""
var i;
for (i=0; i<listedItems.length; i++) {
var tweetObj = listedItems[i]
var currentItem = formatTweetElement(tweetObj)
finalTweetStr += currentItem
}
//console.log(listedItems)
tweetsElement.innerHTML = finalTweetStr
}
xhr.send() //trigger that requests
}
loadTweets(tweetsContainerElement)
// SImple functions for management purposes
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function handleTweetActionBtn(tweet_id, currentCount, action) {
console.log(tweet_id, currentCount)
const url = "/api/tweets/action"
const method = "POST"
const data = JSON.stringify({
id: tweet_id,
action: action
})
const xhr = new XMLHttpRequest()
const csrftoken = getCookie('csrftoken');
xhr.open(method, url)
xhr.setRequestHeader("Content-Type", "application/json")
xhr.setRequestHeader("HTTP_X_REQUESTED_WITH", "XMLHttpRequest")
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
xhr.setRequestHeader("X-CSRFToken", csrftoken)
xhr.onload = function() {
loadTweets(tweetsContainerElement)
}
xhr.send(data)
return
}
function LikeBtn(tweet){
console.log(tweet.id, tweet.likes)
return `<button class='btn btn-primary btn-sm'
onclick=handleTweetActionBtn(${tweet.id},${tweet.likes},'like')>
${tweet.likes} Like</button>`
}
function UnLikeBtn(tweet){
return `<button class='btn btn-outline-primary btn-sm'
onclick=handleTweetActionBtn(${tweet.id},${tweet.likes},'unlike')>
dislike</button>`
}
function RetweetBtn(tweet){
return `<button class='btn btn-outline-success btn-sm'
onclick=handleTweetActionBtn(${tweet.id},${tweet.likes},'retweet')>
share</button>`
}
function formatTweetElement(tweet){
var formattedTweet = "<div class='col-10 border rounded py-4 mb-1 tweet' id='tweet-" + tweet.id + "'>" +
"<p>" + tweet.content + "</p>" +
"<div class='btn-group'>" +
LikeBtn(tweet) +
UnLikeBtn(tweet)+
RetweetBtn(tweet)+
"</div></div>"
return formattedTweet
}
});
</script>
{% endblock %}
I don't think there are issues relating to views and URLs, however for reference they are as;
views.py
@api_view(['POST'])
@permission_classes((permissions.AllowAny, permissions.IsAuthenticated))
def tweet_action_view(request, *args, **kwargs):
serializer = TweetActionSerializer(data = request.data)
if serializer.is_valid(raise_exception=True):
data = serializer.validated_data
tweet_id = data.get("id")
action = data.get("action")
qs = Tweet.objects.filter(id = tweet_id)
if not qs.exists():
return Response({}, status = 404)
obj = qs.first()
if (action == "like") and (request.user in obj.likes.all()):
obj.likes.add(request.user)
serializer = TweetSerializer(obj)
return Response(serializer.data, status = 200)
elif (action == "unlike") and (request.user in obj.likes.all()):
obj.likes.remove(request.user)
elif (action == "retweet"):
pass
return Response({}, status = 200)
and finally urls.py
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("login", views.login_view, name="login"),
path("tweets", views.tweet_list_view, name="tweet_list_view"),
path("tweet-create", views.tweet_create_view, name="tweet_create_view"),
path("tweets/<int:tweet_id>", views.tweet_detail_view, name="tweet_detail_view"),
path("api/tweets/action", views.tweet_action_view, name="tweet_action_view"),
path("api/tweets/<int:tweet_id>/delete", views.tweet_delete_view, name="tweet_delete_view"),
]