OmahaJoe
OmahaJoe

Reputation: 11

angular reset checkbox after ng-change

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

Answers (2)

Jordan Quagliatini
Jordan Quagliatini

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

kind user
kind user

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;

Codepen

Upvotes: 1

Related Questions