1

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"),

]
Lucifer
  • 21
  • 1
  • 4
  • This question deserves an answer. The linked question may offer a solution, but it asks something completely different. At least a comment should explain what the scope has to do with the inline event handler... – biberman Jun 23 '21 at 14:15

0 Answers0