I want to use Javascript's array.filter to remove items from an array, because the syntax is elegant and readable. However, it seems that filter doesn't modify the original array, it just returns a new array, filtered as you requested. My question is, why doesn't the following work as I expect?
$scope.clearList = function () {
this.list = this.list.filter(function (item) {
return item.checked == true;
});
//...
}
I would expect that after returning the newly filtered array, this.list would now hold just the filtered set. It does not work like this however. this.list ends up containing exactly the same items. Altering the code to save out the filtered array in an intermediate variable shows that it is indeed filtering correctly.
I've done a workaround for now, looping through the filtered version and splicing items out of the original list that should be filtered, but this is inelegant. Am I just thinking about it the wrong way?
Sidenote: I'm using Angular.js. I'm unsure it matters at all, but the list comes from the following:
<div class="list" ng-repeat="list in lists">
<!-- ... -->
<ul>
<li ng-repeat="item in list">
<div>
<label>
<input type="checkbox" ng-model="item.checked"/>
{{item.name}}
</label>
<!-- ... -->
</div>
</li>
</ul>
<button class="btn clear-selected" ng-click="clearList()">
Remove Selected
</button>
</div>
Edit to add debugging info: I've introduced a temp variable just to see whats going on in the debugger.
var temp = this.list.filter(function (item) {
return item.checked == true;
});
this.list = temp;
Before execution, this.List has 5 items, temp is undefined. After the first line is executed, this.List has 5 items, and temp has 2 items. After the last line is executed, this.List has 2 items, temp has 2 items.
However, it seems after this that the UI which is bound to this.list does not update. So something unrelated to filter does seem to be going on.
In angular you modify data using the special $scope
variable, and while inside your controller this
points to the $scope
as the executing context, $scope
is preferred.
When the UI doesn't update, it's usually because changes in "models" (or properties of a given scope) are done outside angular. In this case a call to $apply
is needed. This notifies angular that something has changed and to update the views.
However, this doesn't seem to be your issue. I have a working list with minimal changes here http://plnkr.co/edit/Cnj0fEHSmi2L8BjNRAf5?p=preview
Here's the contents of the controller and when you call clearList()
from the UI, only checked items are left in the list.
$scope.list = [
{name: 'one', checked: true},
{name: 'two', checked: false},
{name: 'three', checked: true},
{name: 'four', checked: false}
];
$scope.clearList = function () {
$scope.list = $scope.list.filter(function(item) {
return item.checked === true;
});
};
Now, I'd recommend passing a list to clearList clearList(list)
or even better use Angular filters.
window.list = [1,2,3,4,5,6];
var clearList = function () {
this.list = this.list.filter(function (item) { return item % 2 === 0; });
};
clearList();
console.log(window.list);
Logs [2, 4, 6]
as expected, so I think whatever your bug is is unrelated to filter
.
Are you sure that the array you're modifying with this.list
is the same array that you later come to check?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With