Reputation: 1897
So I've got a base from a source: https://codepen.io/Russbrown/pen/IgBuh?editors=1010 , for a simple to-do list which I will expand upon.
However, when I press the checkbox on an item, the total amount of items needing to be completed does not update.
Here is the code:
index.php:
<!DOCTYPE html>
<html lang="en" ng-app="ToDo">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="Ryan Shah">
<link rel="icon" href="img/favicon.ico">
<title>Todo List - Untitled</title>
<script src="app/angular.js"></script>
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<div class="container" ng-controller="listCtrl">
<p>Remaining Tasks: {{getItems()}}</p>
<ul>
<li ng-repeat="item in list">
<input type="checkbox" ng-model="item.completed" />
<span class="completed-{{item.completed}}">{{item.itemText}}</span>
</li>
</ul>
<form>
<input class="add-input" placeholder="I need to..." type="text" ng-model="newItemText" ng-model-instant />
<button class="add-btn" ng-click="insert()"><h2>Add</h2></button>
</form>
</div>
<script type="text/javascript" src="app/app.js"></script>
</body>
</html>
app.js:
var app = angular.module('ToDo', []);
app.controller('listCtrl', function listCtrl($scope) {
$scope.list = [
{
itemText: 'Hello World',
completed: false
},
{
itemText: 'Hello :)',
completed: false
}
];
$scope.getItems = function() {
return $scope.list.length;
};
$scope.insert = function() {
$scope.list.push({
text: $scope.newItemText,
completed: false
});
$scope.newItemText = '';
};
$scope.clear = function() {
$scope.list = _.filter($scope.list, function(item) {
return !item.completed;
});
};
});
N.B.: I tried using things like ng-true-value
and ng-false-value
on the checkboxes, but that didn't want to work either.
Help is greatly appreciated :)
Upvotes: 2
Views: 118
Reputation: 829
Here is a working plunker based on your code.
I use a variable items instead of getItems so it updates when I change the value from the controller and added a ng-click to the checkbox.
<p>Remaining Tasks: {{items}}</p>
<ul>
<li ng-repeat="item in list">
<input type="checkbox" ng-model="item.completed" ng-click='check(item)'/>
<span class="completed-{{item.completed}}">{{item.itemText}}</span>
</li>
</ul>
And in the controller, I added a function check that increments or decrements if when check or uncheck the check box:
$scope.items = $scope.list.length;
$scope.check = function(item) {
console.log('check ' + item.completed);
if (item.completed) {
$scope.items--;
} else {
$scope.items++;
}
}
$scope.getItems = function() {
return $scope.list.length;
};
$scope.insert = function() {
$scope.list.push({
text: $scope.newItemText,
completed: false
});
$scope.items++;
$scope.newItemText = '';
};
Also,in the insert function I increment 'items' when we add a new item, so the total items left is accurate.
For the clear completed items, I added a button that class clear() via ng-click:
$scope.clear = function() {
console.log('clear');
for (var i = 0; i < $scope.list.length; i++) {
$scope.list[i].completed = false;
}
$scope.items = $scope.list.length;
};
And the HTML:
<button class="add-btn" ng-click="clear()">
<h2>Clear Completed</h2>
</button>
Let us know if that helps.
Upvotes: 2
Reputation: 24864
First, the new items aren't being shown because you have it:
text: $scope.newItemText,
instead of:
itemText: $scope.newItemText,
A snippet working counting the uncompleted items:
(function() {
"use strict";
angular.module('app', [])
.controller('mainCtrl', function($scope) {
$scope.list = [{
itemText: 'Hello World',
completed: false
}, {
itemText: 'Hello :)',
completed: false
}];
$scope.insert = function() {
$scope.list.push({
itemText: $scope.newItemText,
completed: false
});
$scope.newItemText = '';
// Supposing that all items will be added as uncompleted
$scope.listTotal++;
};
// Initialization of listTotal...
$scope.listTotal = $scope.list.filter(function(item) {
return !item.completed;
}).length;
$scope.get_total = function(item) {
// Easy way to increment / decrement the total
$scope.listTotal += item.completed ? -1 : 1;
};
});
})();
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl">
<div class="container">
<p ng-bind="'Remaining Tasks: ' + listTotal"></p>
<ul>
<li ng-repeat="item in list track by $index">
<input type="checkbox" ng-model="item.completed" ng-change="get_total(item)" />
<span class="completed-{{item.completed}}" ng-bind="item.itemText"></span>
</li>
</ul>
<form>
<input class="add-input" placeholder="I need to..." type="text" ng-model="newItemText" ng-model-instant />
<button class="add-btn" ng-click="insert()">
<h2>Add</h2></button>
</form>
</div>
</body>
</html>
I hope it helps.
Upvotes: 1
Reputation: 7734
There is no code to invoke clear, so add to controller:
$scope.$watch('list', $scope.clear, true);
And in view
<p>Remaining Tasks: {{list.length || 0}}</p>
Upvotes: 1