How to remove item from array in Service after using $filter in the Angularjs controller?

Asked

Viewed 959 times

0

I have a Service that provides a list of tasks. After getting this list by injecting dependencies into my controller I select a filter to order the completed tasks (task.done == true) to be last in the view list.

The problem is that after I apply the filter, the entries in the list are modified and I can no longer remove the item. Below my code.

app.service('Tasks', function() {
 var tasks = [
    {
       "id": 1,
       "name" : "Tomar café",
       "done" : false
    },
    {
       "id": 2,
       "name" : "Fazer Torrada",
       "done" : false
    },
    {
       "id": 3,
       "name" : "Limpar a casa",
       "done" : true
    }];

    this.getList = function() {
        return tasks;
    };

    this.removeTask = function(task) {
        tasks.splice(tasks.indexOf(task), 1);
    };

    this.setDone = function(index, task) {
        tasks.splice(index, 1, task);
    };

    this.saveTask = function(task) {
        tasks.push(task);
    };

});



app.controller('IndexCtrl', function($scope, Tasks, $filter) {

$scope.tasks = Tasks.getList();
$scope.tasks = $filter('orderBy')($scope.tasks, 'done', false);

$scope.removeTask = function (task) {
    Tasks.removeTask(task);
};






 });
  • Where are you passing the method of Tasks.removeTask(task) in his $scope.tasks? Would not be: $scope.tasks = Tasks.removeTask($scope.tasks);

  • If it’s in the view, I believe it would be something like: ng-repeat="task in tasks | filter: removeTask"

2 answers

1

Index is modified because your list does not have an attribute track by, it is used so that the angle can find the object and mark it if you do not enter the track by, it automatically creates a key called $$hash, which makes the object different.

To solve the problem, your screen should have in ng-repeat a text more so less: ng-repeat="task in tasks track by task.id"

More information can be found in the documentation here: https://docs.angularjs.org/api/ng/directive/ngRepeat

1


If your tasks have ID’s that are unique identifiers, they cannot be removed by the same from the list?

Note that when using the filter the angular has to make internal modifications to the objects so that they reposition inside the repeat.

Could use the track by as our friend Ricardo suggested, but I will leave here another solution suggestion that can be applied in many other parts of your project.

First we will add to every Array type object a new behavior through its prototype, thus doing.

Array.prototype.removeByAttr = function (valOfAttr, attr) {
    var i = this.length;

    while (i--) {
        if (this[i].hasOwnProperty(attr) && (this[i][attr] == valOfAttr)) {
            this.splice(i, 1);
            return;
        }
    }

    throw 'not found';
};

This new behavior added to array types looks for an object by its specific attribute and removes it from the list if it finds that value in that attribute. Doing a reverse while which is much faster since the order of the loop here doesn’t matter.

And then to use just just do that.

    this.removeTask = function(task) {
        tasks.removeByAttr(task.id, "id");
    };

And just like that.

This concept can be applied to all your array operations because it makes you reuse the code, and can still create unit tests that make sure this new behavior is always OK.

I hope I’ve helped.

  • Man, thanks for sharing this other way of doing it, I found it very interesting. I have one question left in the excerpt where you say "Doing a reverse while which is much faster since the order of the loop here doesn’t matter." , this is relative right? since the item can be both at the beginning of the while, and at the end, this has no way to predict, check?

  • @Ricardorodriguesdefaria is relative to the following factor, "Do I care about the order of my items within the loop?" in this specific case no, because as you said yourself it can be at the beginning or at the end of the array and to make validations and checks for it is much more expensive than simply to go through the list in reverse. You can have a look at some tests here https://blog.jcoglan.com/2010/10/i-am-a-fast-loop/

  • And the reverse while becomes faster because it does not need to validate the end of the loop because when it reaches 0 o while will become false and exit alone.

  • Of course there are many other forms of search, binary search, deep search, search on nodes and etc, etc. For such a simple case is not worth the implementation of something so complicated or sophisticated.

  • Certainly, thank you for clarifying and sharing the post.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.