PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, September 8, 2022

[FIXED] Why isn't my Jquery code working after the second form submit? Django - Ajax - Jquery

 September 08, 2022     ajax, django, html, jquery     No comments   

Issue

I have a follow/unfollow button. Currently my Jquery is working on the first submit but when I toggle the button again, the Jquery doesn't change any of the elements.

html

    {% for user in followers %}
<div class="flist" id="flist-{{ user.profile.pk }}">
    <article class="media comment-section"> 
    <a class="mr-2" href="{% url 'user-posts' user %}"> 
    <img class="rounded-circle comment-img" src="{{ user.profile.image.url }}"></a>
        <div class="media-body mt-1">

        {% if user.profile in following %}
        <div class="remove-follower-div-{{ user.profile.pk }}">
            <form method="POST" action="{% url 'remove-follower-js' user.profile.pk %}" class="remove-follower-form" id="{{ user.profile.pk }}">
            {% csrf_token %}
            <button class="btn btn-unfollow unfollow-link" type="submit" style="float:right;" id="unfollow-button-{{ user.profile.pk }}"><span>Following</span></button>
            </form>
        </div>
        {% else %}
        <div class="add-follower-div-{{ user.profile.pk }}">
            <form method="POST" action="{% url 'add-follower-js' user.profile.pk %}" class="add-follower-form" id="{{ user.profile.pk }}">
            {% csrf_token %}
            <input type="hidden" name="profile_id" value="{{ user.profile.pk }}">
            <button class="btn btn-follow btn-light side-link mr-4" type="submit" style="float:right;" id="follow-button-{{ user.profile.pk }}">Follow</button>
            </form>
        </div>
        {% endif %}

.js file

$( document ).ready(function() {


$('.add-follower-form').on("submit", function(e) {
    e.preventDefault();
    const profile_id = $(this).attr('id');
    
    console.log(profile_id)

    const url = $(this).attr('action');
    console.log(url)

    $.ajax({
        type: 'POST',
        url: url,
        data: {
            'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
            'profile_id':profile_id,
        },
        dataType: 'json',
        success: function(response) {
            console.log('success')
            console.log(response)
            console.log(profile_id)
            console.log(url)
            
            $(`.add-follower-div-${profile_id}`).find('.add-follower-form').attr('action', "/profile/"+ profile_id + "/followers/remove/js");
            $(`.add-follower-div-${profile_id}`).find('.add-follower-form').attr('class', "remove-follower-form");
            $(`.add-follower-div-${profile_id}`).attr('class', `remove-follower-div-${profile_id}`);
            $(`#follow-button-${profile_id}`).attr('class',"btn btn-unfollow unfollow-link");
            $(`#follow-button-${profile_id}`).empty();
            $(`#follow-button-${profile_id}`).append('<span>Following</span>');
            $(`#follow-button-${profile_id}`).attr('id',"unfollow-button-"+profile_id);
            
        },
        error: function(response) {
            console.log('error', response);
        }
    });
});


$('.remove-follower-form').on("submit", function(e) {
    e.preventDefault();
    const profile_id = $(this).attr('id');
    
    console.log(profile_id)

    const url = $(this).attr('action');
    console.log(url)

    $.ajax({
        type: 'POST',
        url: url,
        data: {
            'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
            'profile_id':profile_id,
        },
        dataType: 'json',
        success: function(response) {
            console.log('success')
            console.log(response)
            console.log(profile_id)
            console.log(url)
            
            $(`.remove-follower-div-${profile_id}`).find('.remove-follower-form').attr('action', "/profile/"+ profile_id + "/followers/add/js");
            $(`.remove-follower-div-${profile_id}`).find('.remove-follower-form').attr('class', "add-follower-form");
            $(`.remove-follower-div-${profile_id}`).attr('class', `add-follower-div-${profile_id}`);
            $(`#unfollow-button-${profile_id}`).attr('class',"btn btn-follow btn-light side-link mr-4");
            $(`#unfollow-button-${profile_id}`).find('span').remove();
            $(`#unfollow-button-${profile_id}`).text("Follow");
            $(`#unfollow-button-${profile_id}`).attr('id',"follow-button-"+profile_id);
            
        },
        error: function(response) {
            console.log('error', response);
        }
    });
});
});

views.py

#AJAX RESPONSE FOR FOLLOWERS.HTML, FOLLOWING.HTML
def add_follower_js(request, *args, **kwargs):
if request.method == 'POST':
    pk = request.POST.get('profile_id')
    profile = Profile.objects.get(pk=pk)
    profile.followers.add(request.user)

    data = {
        'success': '1',
    }
    return JsonResponse(data, safe=False, status=200)
return redirect(request.META.get('HTTP_REFERER', 'redirect_if_referer_not_found'))

def remove_follower_js(request, *args, **kwargs):
if request.method == 'POST':
    pk = request.POST.get('profile_id')
    profile = Profile.objects.get(pk=pk)
    profile.followers.remove(request.user)

    data = {
        'success': '1',
    }
    return JsonResponse(data, safe=False, status=200)
return redirect(request.META.get('HTTP_REFERER', 'redirect_if_referer_not_found'))

urls.py

path('profile/<int:pk>/followers/add/js', user_views.add_follower_js, name='add-follower-js'),
path('profile/<int:pk>/followers/remove/js', user_views.remove_follower_js, name='remove-follower-js'),

enter image description here

Example: If the button is currently (showing Following):

        <div class="remove-follower-div-{{ user.profile.pk }}">
        <form method="POST" action="{% url 'remove-follower-js' user.profile.pk %}" class="remove-follower-form" id="{{ user.profile.pk }}">
        {% csrf_token %}
        <button class="btn btn-unfollow unfollow-link" type="submit" style="float:right;" id="unfollow-button-{{ user.profile.pk }}"><span>Following</span></button>
        </form>
    </div>

I click it, the button submits the form, view returns sucessfully, and button html is changed to (showing Follow):

        <div class="add-follower-div-{{ user.profile.pk }}">
        <form method="POST" action="{% url 'add-follower-js' user.profile.pk %}" class="add-follower-form" id="{{ user.profile.pk }}">
        {% csrf_token %}
        <input type="hidden" name="profile_id" value="{{ user.profile.pk }}">
        <button class="btn btn-follow btn-light side-link mr-4" type="submit" style="float:right;" id="follow-button-{{ user.profile.pk }}">Follow</button>
        </form>
    </div>

But when I click it again, the html doesn't change back to showing Following. The url and all the html stays the same.. what am I doing wrong..


Solution

I spent a few minutes looking through your code to see what the error might be but honestly I think there's a fundamentally better way of doing this that isn't so repetitive and cumbersome, JS-wise. I would suggest having a single view and url for toggling whether someone is a follower or not. It will make everything so much simpler. See below:

# template - a single form, the if-statement controls the text only
<form method="POST" 
    class="follower-form" 
    action="{% url 'toggle-following' user.profile.pk %}">
    {% csrf_token %}
    <button class="btn" type="submit" style="float:right;">
        {% if user.profile in following %}
        Following
        {% else %}
        Follow
        {% endif %}
    </button>
</form>

Then we let the view to do the lifting, note the name change. I also changed the URL but I'm sure you know how to change this. We have a simple if-statement that checks whether someone is already following or not, it sets the action accordingly and determines the response. I have changed the JSON response to a simple HTTP response because you don't need JSON here:

def toggle_follower(request, pk):
    if request.method != 'POST':
        return redirect(... # truncated

    profile = Profile.objects.get(pk=pk)

    if request.user not in profile_followers.all():
        profile.followers.add(request.user)
        return HttpResponse("Following") # JSON response is unnecessary
    else:
        profile.followers.remove(request.user)
        return HttpResponse("Follow")

As we are determining the value on the server and we only have a single form that handles both follow/unfollow functions, your Jquery then becomes far more concise:

$('.follower-form').on("submit", function(e) {
    e.preventDefault();
    const url = $(this).attr('action');

    $.ajax({
        type: 'POST',
        url: url,
        data: {
            'csrfmiddlewaretoken': ... // truncated
        },
        success: function(response) {
          // simply set the button text to the response
          e.target.innerText = response
        },
        ...
    });
});


Answered By - 0sVoid
Answer Checked By - David Goodson (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing