I have this knockout code:
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());
This html:
<head>
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="knockout-2.0.0.js"></script>
<script type="text/javascript" src="script.js"></script>
</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>
</body>
The example is the same as the one found on the Knockout website, but when I run it, it returns this message on Chrome Fire Bug:
Uncaught TypeError: Cannot read property 'nodeType' of null
This one is related to the knockout file and to this line of my script:
ko.applyBindings(new TaskListViewModel());
And this error is pointing to this line (1766) on knockout:
var isElement = (nodeVerified.nodeType == 1);
What am I doing wrong?
You have a simple spelling mistake:
Should be:
if you have jQuery put apply binding inside
onload
so that knockout looks for the DOM when DOM is ready.You might want to consider using the jquery ready handler for this
Then you achieve two things:
See http://api.jquery.com/ready/
This problem was happening because I was trying to bind an
HTML
element before it was created.My script was loaded on top of the
HTML
(in the head) but it needed to be loaded at the bottom of myHTML
code (just before the closing body tag).Thanks for your attention James Allardice.
A possible workaround is using
defer="defer"
Use this if the script is not going to generate any document content. This will tell the browser that it can wait for the content to be loaded before loading the script.
Further reading.
Hope it helps.