Knockout.js: Unable to parse bindings from JSON

心已入冬 提交于 2019-12-11 03:46:53

问题


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 :/


回答1:


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.

function TaskViewModel() {
    var self = this;
    self.task = ko.observable();

    $.getJSON('/data', function(data){
        self.task(new Task(data));
    });
}

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.

function TaskViewModel() {
    var self = this;
    self.task = new Task();

    $.getJSON('/data', function(data){
        self.task.init(data);
    });
}

function Task() {
    var self = this;
    self.id = ko.observable();
    self.question = ko.observable();
    self.alternatives = ko.observableArray();

    self.init = function (data) {
        self.id(data.id);
        self.question(data.question);
        self.alternatives(ko.utils.arrayForEach(data.alternatives, function (item) {
            return new Alternative(item.alternative, item.correct);
        }));
    };
}



回答2:


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.

<div data-bind="with: selecteditem">
    <form>
        <fieldset>
            <div>
                <label>first name</label>
                <input data-bind="value: firstname"></input>
            </div>
            <div>
                <label>lasst name</label>
                <input data-bind="value: lastname"></input>
            </div>
        </fieldset>
        <div>
            <a href="#" data-bind="click: $root.savechanges">Save</a>
        </div>
    </form>
</div>


来源:https://stackoverflow.com/questions/13333567/knockout-js-unable-to-parse-bindings-from-json

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!