Home > OS >  Why isn't my Jquery code working after the second form submit? Django - Ajax - Jquery
Why isn't my Jquery code working after the second form submit? Django - Ajax - Jquery

Time:08-07

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  id="flist-{{ user.profile.pk }}">
    <article > 
    <a  href="{% url 'user-posts' user %}"> 
    <img  src="{{ user.profile.image.url }}"></a>
        <div >

        {% if user.profile in following %}
        <div >
            <form method="POST" action="{% url 'remove-follower-js' user.profile.pk %}"  id="{{ user.profile.pk }}">
            {% csrf_token %}
            <button  type="submit" style="float:right;" id="unfollow-button-{{ user.profile.pk }}"><span>Following</span></button>
            </form>
        </div>
        {% else %}
        <div >
            <form method="POST" action="{% url 'add-follower-js' user.profile.pk %}"  id="{{ user.profile.pk }}">
            {% csrf_token %}
            <input type="hidden" name="profile_id" value="{{ user.profile.pk }}">
            <button  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 >
        <form method="POST" action="{% url 'remove-follower-js' user.profile.pk %}"  id="{{ user.profile.pk }}">
        {% csrf_token %}
        <button  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 >
        <form method="POST" action="{% url 'add-follower-js' user.profile.pk %}"  id="{{ user.profile.pk }}">
        {% csrf_token %}
        <input type="hidden" name="profile_id" value="{{ user.profile.pk }}">
        <button  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..

CodePudding user response:

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" 
     
    action="{% url 'toggle-following' user.profile.pk %}">
    {% csrf_token %}
    <button  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
        },
        ...
    });
});
  • Related