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

0

I have a Service that provides a to-do list. After getting this list through the dependency injection in my controller I set a filter to order that completed tasks (task.done == true) are last in the view list.

The problem is that after I apply the filter, the indexes 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);
};






 });
    
asked by anonymous 30.10.2015 / 04:49

2 answers

1

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

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

I could use track by as our friend Ricardo suggested, but I'll leave here another suggestion of a solution that can be applied to many other parts of your project.

First let's add to every Array type object a new behavior through its prototype, doing so.

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 is much faster since the order of the loop here does not matter.

And then to use just do just that.

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

And that's it.

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

I hope I have helped.

    
30.10.2015 / 12:40
1

The indexes are modified because your list does not have a track by attribute, it is used so that the angle can find the object and mark it, in case you do not enter track by , it automatically creates a key called $ $ hash, which causes the object to be different.

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

More information can be found in the documentation here: link

    
30.10.2015 / 12:24