Reputation: 11
exploring Angular, I built a simple to-do list.
My issue is that when I use the checkbox to delete an item, say the very last one, the item is deleted but the checkbox above it becomes "checked." I just want to be able to delete the item via the checkbox and all the other checkboxes will remain unchecked. I can't figure the bug here. Dimly, I was thinking I needed to reset the "checked" variable, but that wasn't working.
angular.module('ToDo', [])
.controller('ToDoController', function ($scope, ToDoService) {
$scope.items = ToDoService.items;
$scope.checked = false;
$scope.add = function() {
ToDoService.add($scope.todo);
};
$scope.deleteItem = function() {
ToDoService.deleteItem();
};
$scope.remove = function(idx) {
this.items.splice(idx, 1);
console.log("test inside remove");
return this.items;
};
})
.factory('ToDoService', function () {
return {
items: [],
add: function(todo) {
this.items.push({todo: todo, time: new Date()});
},
deleteItem: function(idx) {
this.items.splice(idx, 1);
console.log("test inside deleteItem");
}
};
});
<html ng-app='ToDo'>
<head>
<title>My Angular To-Do App</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src='app.js'></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="app.css">
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#">My Angular To-Do App</a>
</div>
</div>
</nav>
<div class="container todos" ng-controller='ToDoController'>
<div class="starter-template">
<h1>My To-Do's</h1>
<div class="alert alert-info" role="alert" ng-show="!items.length">
No to-do items have been added yet.
</div>
<ul>
<li ng-repeat='item in items'>{{item.todo}} - {{item.time}} <a class="btn" ng-click="remove()">Delete</a>
<input type="checkbox" ng-model="checked" ng-change="deleteItem(checked)" >
</li>
</ul>
<form class="form-inline">
<input type='text' ng-model='todo' class="form-control" />
<button ng-click='add()' class="btn btn-default">Add</button>
</form>
</div>
</div>
</body>
</html>
Upvotes: 1
Views: 1061
Reputation: 193
There are multiple bugs in your application. In your situation, you are calling ToDoService.deleteItem without any parameters when your checkbox change boolean state. So, basically you are doing a this.items.splice(undefined, 1);
which removes the first element (indeed what happens in your codepen).
You should change the signature of your deleteItem methods in your service and controller to take the name of the todo. Then, you only have to search it and remove it from the list.
.factory('ToDoService', function() {
return {
....
deleteItem: function(itemStr) {
delete this.items[this.items.findIndexOf(function(item) {
return item ==== itemStr;
})];
},
}
})
then in your template you should call remove with the current todo
ng-change="remove(item.todo)"
Using Kind User answer is even simpler, because you have the direct index of your component,
.factory('ToDoService', function() {
return {
....
deleteItem: function(idx) {
delete this.items[idx];
},
}
})
Upvotes: 0
Reputation: 41893
You have complicated your app, using factory is unnecessary here. Another thing - your ng-repeat
function didn't set id
's of added todos - you were deleting always the first element every time you clicked on delete
or on checkbox
.
ng-repeat='(id, item) in items'
Lastly - I've added a new feature. With every submit of the todo, the todo input gets cleared.
$scope.todo = null;
Upvotes: 1