I’m looking at the Task List example from Knockouts site and having a problem understanding how a particular value is being set.
There is a javascript object created called Task. It has a boolean property of ‘isDone’ that is assigned through this.isDone = ko.observable(data.isDone);
My problem is that I don’t understand how the value of true or false is being passed to this property. There is no sign that it is being passed in the initial creation of the object, and the only other place in the javascript file that is using the value is this:
self.incompleteTasks = ko.computed(function() {
return ko.utils.arrayFilter(self.tasks(), function(task) {
return !task.isDone()
});
But this is only for the totals at the bottom of the task list – and this can be completely removed and the app still will work fine (except of course you won’t have totals).
In the markup, though, the ‘isDone’ value is being used by the checkbox input:
<input type="checkbox" data-bind="checked: isDone" />
Is it possible that when the checkbox is checked, the checkbox value itself – which would be true – is passed into ‘isDone’?
Normally, I would expect that ‘isDone’ would need to already have a ‘true’ or ‘false’ value associated with it to be used in the markup, but I don’t see how the value is being assigned.
Here’s the complete code for context:
function Task(data) {
this.title = ko.observable(data.title);
this.isDone = ko.observable(data.isDone);
}
function TaskListViewModel() {
// Data
var self = this;
self.tasks = ko.observableArray([]);
self.newTaskText = ko.observable();
self.incompleteTasks = ko.computed(function() {
return ko.utils.arrayFilter(self.tasks(), function(task) {
return !task.isDone()
});
});
// Operations
self.addTask = function() {
self.tasks.push(new Task({ title: this.newTaskText() }));
self.newTaskText("");
};
self.removeTask = function(task) { self.tasks.remove(task) };
}
ko.applyBindings(new TaskListViewModel());
… and here’s the markup:
<!DOCTYPE html>
<html>
<head>
<title>Knockout Practice</title>
</head>
<body>
<h3>Tasks</h3>
<form data-bind="submit: addTask">
Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" />
<button type="submit">Add</button>
</form>
<ul data-bind="foreach: tasks, visible: tasks().length > 0">
<li>
<input type="checkbox" data-bind="checked: isDone" />
<input data-bind="value: title, disable: isDone" />
<a href="#" data-bind="click: $parent.removeTask">Delete</a>
</li>
</ul>
You have <b data-bind="text: incompleteTasks().length"> </b> incomplete task(s)
<span data-bind="visible: incompleteTasks().length == 0"> - it's beer time!</span>
<script type='text/javascript' src='javascript/jquery-1.6.4.js'></script>
<script type='text/javascript' src='javascript/jquery-tmpl.js'></script>
<script type='text/javascript' src='javascript/knockout-2.0.0.js'></script>
<script type='text/javascript' src='javascript/myKnockoutCode.js'></script>
</body>
</html>
The
checkedbinding determines if it is true or false loosely. This means that 0, empty string, null, false, NaN, and undefined would be considered false.So, it is not important for
isDoneto actually be initialized to false.When the checkbox is checked or unchecked, the
checkedbinding will properly set it totrueorfalse.