0

I'm trying to create a favorite function in my django template that let user click on the icon and it will call to an api i made to send add and remove that favorite item from user data.

favorite and unfavorite button

Currently how it work is if user click on the icon(favorite or unfavorite) it will call to an api that handle add favorite or remove favorite, and also it will replace the DOM of that tag with the opposite (for example if i click on favorite then the entire tag of it will be replace with tag content that has unfavorite icon and onclick function)

here my html for the tag, it display base on if it is favorite or not( {% %} tag is django handling it ):

<div class="article-category">{{ property.get_type_display }}
     <div class="bullet"></div> {{ property.publish_date|date:'d-m-Y' }}
     {% if not request.user|is_favorite:property.id %}
         <a id="mylink" href="javascript:onclickFunction()" value="{{ property.id }}">
            <i class="far fa-heart fa-lg" style="color: red" title="Add to favorite"></i>
         </a>
      {% else %}
          <a id="mylink2" href="javascript:onclickFunction()" value="{{ property.id }}">
             <i class="fas fa-heart fa-lg" style="color: red" title="Remove from favorite"></i>
          </a>
      {% endif %}
 </div>

And here is my jquery script:

<script>
    $(document).ready(function () {
            $('#mylink').on('click', function (event) {
                event.preventDefault();
                property_id = $(this).attr("value")
                $.ajax({
                    type: "POST",
                    url: "http://localhost:9999/api/add_favorite/" + property_id + "/",
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader('Authorization', 'Bearer {{ refresh_token }}');
                    },
                    success: function (data) {
                        if (data.code == 200) {
                            alert('ok');
                            replace_part_1 = '<a id="mylink2" href="javascript:onclickFunction()" value="' + property_id +'"><i class="fas fa-heart fa-lg" style="color: red" title="Remove from favorite></i></a>'
                            $("#mylink").replaceWith(replace_part_1);
                        }
                    }
                });
                return false;
            });
            $('#mylink2').on('click', function (event) {
                event.preventDefault();
                property_id = $(this).attr("value")
                $.ajax({
                    type: "DELETE",
                    url: "http://localhost:9999/api/remove_favorite/" + property_id + "/",
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader('Authorization', 'Bearer {{ refresh_token }}');
                    },
                    success: function (data) {
                        if (data.code == 200) {
                            alert('ok');
                            replace_part_2 = '<a id="mylink" href="javascript:onclickFunction()" value="' + property_id +'"><i class="far fa-heart fa-lg" style="color: red" title="Add to favorite"></i></a>'
                            $("#mylink2").replaceWith(replace_part_2);
                        }
                    }
                });
                return false;
            });
        });
</script>

Now the first time i click on favorite or unfavorite it sent to the api and work, the replace html part for "#mylink2" onclick event but the "#mylink" replace doesn't include the tag which contain the icon.

After this any clicking event after that won't work and i have to refresh the page to click it again to work. Any click event after that also return this error:

Uncaught ReferenceError: onclickFunction is not defined at :1:1

I'm super noob at jquery so i can't seem to find what is wrong, hope someone can help me

EDIT:

i changed my script to this by replace with value attribute of anchor tag:

<script>
    $(document).ready(function () {
            $('.article-details').on('click', '#mylink', function(event) {
                event.preventDefault();
                property_id = $(this).attr("value")
                $.ajax({
                    type: "POST",
                    url: "http://localhost:9999/api/add_favorite/" + property_id + "/",
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader('Authorization', 'Bearer {{ refresh_token }}');
                    },
                    success: function (data) {
                        if (data.code == 200) {
                            alert('ok');
                            replace_part_1 = '<a id="mylink2" href="#" value="' + property_id +'"><i class="fas fa-heart fa-lg" style="color: red" title="Remove from favorite></i></a>'
                            $("a[value='" + property_id + "']").replaceWith(replace_part_1);
                        }
                    }
                });
                return false;
            });
            $('.article-details').on('click', '#mylink2', function(event) {
                event.preventDefault();
                property_id = $(this).attr("value")
                $.ajax({
                    type: "DELETE",
                    url: "http://localhost:9999/api/remove_favorite/" + property_id + "/",
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader('Authorization', 'Bearer {{ refresh_token }}');
                    },
                    success: function (data) {
                        if (data.code == 200) {
                            alert('ok');
                            replace_part_2 = '<a id="mylink" href="#" value="' + property_id +'"><i class="far fa-heart fa-lg" style="color: red" title="Add to favorite"></i></a>'
                            $("a[value='" + property_id + "']").replaceWith(replace_part_2);
                        }
                    }
                });
                return false;
            });
        });
</script>

and my html to:

<div class="article-category">{{ property.get_type_display }}
                                <div class="bullet"></div> {{ property.publish_date|date:'d-m-Y' }}
                                {% if not request.user|is_favorite:property.id %}
                                <a id="mylink" href="#" value="{{ property.id }}">
                                    <i class="far fa-heart fa-lg" style="color: red" title="Add to favorite"></i>
                                </a>
                                {% else %}
                                <a id="mylink2" href="#" value="{{ property.id }}">
                                    <i class="fas fa-heart fa-lg" style="color: red" title="Remove from favorite"></i>
                                </a>
                                {% endif %}
                            </div>

it worked but the onclick of #mylink when changing the html the i tag inside still disappear(the #mylink2 onclick worked it changed the html white the tag)

Linh Nguyen
  • 3,452
  • 4
  • 23
  • 67

1 Answers1

1

It looks like you are facing an event delegation problem. That is, the moment your jQuery code runs, $('#mylink2') does not exist in the document and hence the event doesnt get binded. Use event delegation instead:

$('.article-category').on('click', '#mylink2', function(event) {
   event.preventDefault();
   // your original click handler
});

#myParentWrapper should be an element that is consistent in your markup, preferably not body or document for performance reasons.

You can then remove the onclick attribute from your anchor - or - actually somewhere define the function that is referenced there if it should do anything other than what your jQuery code does already.

Alex
  • 9,911
  • 5
  • 33
  • 52