ctzdev
ctzdev

Reputation: 676

AJAX jQuery on click dynamically created only works first time

I am trying to create a dropdown menu that I dynamically insert into using jQuery. The objects I'm inserting are notifications, so I want to be able to mark them as read when I click them.

I have an AJAX call that refreshes the notifications every second from the Django backend.

Once it's been refreshed, I insert the notifications into the menu.

I keep an array of the notifications so that I don't create duplicate elements. I insert the elements by using .append(), then I use the .on() method to add a click event to the <li> element.

Once the click event is initiated, I call a function to .remove() the element and make an AJAX call to Django to mark the notification as read.

Now my problem:

The first AJAX call to mark a notification as read always works. But any call after that does not until I refresh the page. I keep a slug value to identify the different notifications.

Every call I make before the refresh uses the first slug value. I can't figure out why the slug value is tied to the first element I mark as read.

Also, if anyone has a better idea on how to approach this, please share.

Here's my code:

var seen = [];

function removeNotification(elem, urlDelete) {
    elem.remove();
    console.log("element removed");

    $.ajax({
        url: urlDelete,
        type: 'get', 
        success: function(data) {
            console.log("marked as read");
        },
        failure: function(data) { 
            console.log('failure to mark as read');
        }
    }); 
}

function insertNotifications(data) {
    for (var i = 0; i < data.unread_list.length; i++) {
        var slug = data.unread_list[i].slug
        var urlDelete = data.unread_list[i].url_delete;
        if (seen.indexOf(slug) === -1) {

            var elem = $('#live-notify-list').append("<li id='notification" +
                i + "' > " + data.unread_list[i].description + " </li>");

            var parent = $('#notification' + i).wrap("<a href='#'></a>").parent();

            seen.push(slug);

            $( document ).ready(function() {
                    $( document ).on("click", "#notification" + i, function() {
                    console.log("onclick " + slug);
                    removeNotification(parent[0], urlDelete);
                });
            });
        }
    }
}

function refreshNotifications() {
    $.ajax({
        url: "{% url 'notifications:live_unread_notification_list' %}",
        type: 'get',
        success: function(data) {
            console.log("success");
            insertNotifications(data);
        },
        failure: function(data) { 
            console.log('failure');
        }
    }); 
}
setInterval(refreshNotifications, 1000);

Upvotes: 0

Views: 359

Answers (1)

Mohamed-Yousef
Mohamed-Yousef

Reputation: 24001

I really don't know what do you mean with parent[0] in

removeNotification(parent[0], urlDelete);

I think you can simply try $(this)

removeNotification($(this), urlDelete);

but to be honest I find to put

$( document ).ready(function() {
   $( document ).on("click", "#notification" + i, function() {
      console.log("onclick " + slug);
      removeNotification(parent[0], urlDelete);
   });
});

inside a loop .. its bad thing try to put it outside a function and use it like

$( document ).ready(function() {
       setInterval(refreshNotifications, 1000);
       $( document ).on("click", "[id^='notification']", function() {
          console.log("onclick " + slug);
          removeNotification($(this), urlDelete);
       });
 });

and try to find a way to pass a urlDelete which I think it will be just one url

Upvotes: 1

Related Questions