I have a view model that fetches JSON through AJAX, and creates a new Task, but Knockout keep giving me a binding error.
If I hard code the data coming from the server straight in my view model, I don't receive any errors.
My view model creates new task, that has an id, a question and a number of alteratives, which in itself has a text and correct boolean flag.
The following code works perfectly fine:
function Task(data) {
var self = this;
self.id = data.id;
self.question = ko.observable(data.question);
var alts = new Array();
$(data.alternatives).each(function(index){
alts.push(new Alternative(data.alternatives[index].alternative, data.alternatives[index].correct));
});
self.alternatives = ko.observableArray(alts);
}
function Alternative(alternativeText, correctAnswer) {
var self = this;
self.alternative = ko.observable(alternativeText);
self.correct = ko.observable(correctAnswer);
}
function TaskViewModel() {
var self = this;
var data = {
id: 5,
question: 'test',
alternatives: [{
alternative: 'alt 1',
correct: false
},{
alternative: 'alt 2',
correct: true
},{
alternative: 'alt 3',
correct: false
}]
};
self.task = new Task(data);
}
But if I exhcange the hard coded data
variable with real data from the server:
function TaskViewModel() {
var self = this;
$.getJSON('/data', function(data){
self.task = new Task(data);
});
}
Knockout gives me this error:
Error: Unable to parse bindings.
Message: ReferenceError: Can't find variable: task;
Bindings value: value: task.question
The data from the URL looks like the following:
{"id":5,"question":"test","alternatives":[{"alternative":"alt 1","correct":false},{"alternative":"alt 2","correct":true},{"alternative":"alt 3","correct":false}]}
I can't seem to figure out why this won't work :/
Your view model doesn't actually have a
task
property by the time your bindings are applied. You need to give it something to bind to.There's a couple of ways you can handle this.
Probably the easiest way would be to make
task
observable and set it as the result of the ajax call. You may need to adjust you bindings to account for this change.A more flexible option would be to add a separate initialization method for your
Task
objects and set the task (uninitialized). Then as a result of the ajax call, call the initialization method to initialize it. You would have to adjust the initialization code for your task objects of course.This post contains a number of ways you can handle binding when source is null.
KnockoutJS binding when source is null/undefined
If you're OK with your unbindable UI from disappearing I recommend using
with
If
selectedItem
is null then the element won't even be shown.