0

I have an event that attempts to remove items from a list. Currently trying to use splice to remove them from the array of objects. I need to use a function that acutally uses the original array. As I want so see the change happen live in the frontend. The code below works to a certain extent, but only seems to remove some items per click.

Controller

$scope.clearAlerts = function(type) {
        var array = [];
        for (let item of $scope.notifications) { 
            if (item.read && type == 'seen') {
                notifications.clearAlerts(item.watching_id);
                //console.log(item.watching_id)
            }

            if (!item.read && type == 'notseen') {
                notifications.clearAlerts(item.watching_id);
                //console.log(item.watching_id)  - This returns 8 items
            }
        }
    }

Service

this.clearAlerts = function(watchingId = null) {
        // Remove notifications
        this.notifications.forEach((item, index, object) => {
            if (item.watching_id === watchingId) {
                //remove alerts from dom
                object.splice(index, 1); - This only removes 2 or 3 per click
                index--;
                // update database
                //return api.request('GET', 'notification/' + watchingId + '/clear', {watching_id: watchingId});
            }
        });
    }

Any help on this would be much appreciated. Thanks

1
  • I would suggest using an object whose keys are your ids instead of using an array, that way you can call for instance delete notifications['id'] to delete from the object with no stress Commented Feb 28, 2021 at 19:29

2 Answers 2

2

So if you were to use an object instead of an array where the keys of the object were say the ID you are watching then your service function should look something like this...

this.clearAlerts = function(watchingId = null) {
    delete this.notifications[watchingId];
}

Much simpler, so the idea is that instead of using an array as in [object, object], us an object that is mapped out something like so

{
    id1: object,
    id2: object,
    ...
}

where id1, and id2 are actually taken from watching_id which you defined

Sign up to request clarification or add additional context in comments.

Comments

2

As for the reason why your alerts aren't removed accurately is because you are mutating the array you are looping through. Here is an example

const notifications = [
  {
    watching_id: 1
  },
  {
    watching_id: 2
  },
  {
    watching_id: 3
  },
  {
    watching_id: 4
  }
];

notifications.forEach((item,index, arr) => {
  if (item.watching_id > 0) {
    arr.splice(index, 1);
  }
})

In this example at first sight it can seem that all items are going to be deleted, but that is not the case.

When the index is 0, you delete the first item, and after deletion you have an array with 3 items, so on the second iteration when the index is 1 you are deleting the item from 3 items array which index is 1 and that is the second item out of 3, the first item is intact.

As a solution you can add the third argument to the splice, in order to have the same length array, which will solve the problem. Decide yourself what is best for your specific case, 3rd argument can be anything null,'undefined' or an object object.splice(index, 1, {}).

By the way, index-- doesn't do anything, index is set on every iteration.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.