2

AJAX を介して JSON を取得し、新しいタスクを作成するビュー モデルがありますが、Knockout はバインディング エラーを出し続けます。

サーバーからのデータをビュー モデルに直接ハード コーディングすると、エラーは発生しません。

私のビューモデルは、ID、質問、およびいくつかの選択肢を持つ新しいタスクを作成します。これには、テキストと正しいブールフラグがあります。

次のコードは問題なく動作します。

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);
}

しかし、ハードコードされたdata変数をサーバーからの実際のデータと交換すると、次のようになります。

function TaskViewModel() {
    var self = this;

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

ノックアウトで次のエラーが表示されます。

Error: Unable to parse bindings.
Message: ReferenceError: Can't find variable: task;
Bindings value: value: task.question

URL からのデータは次のようになります。

{"id":5,"question":"test","alternatives":[{"alternative":"alt 1","correct":false},{"alternative":"alt 2","correct":true},{"alternative":"alt 3","correct":false}]}

なぜこれがうまくいかないのか理解できないようです:/

4

2 に答える 2

6

taskバインディングが適用されるまで、ビュー モデルには実際にはプロパティがありません。バインドするものを与える必要があります。

これを処理するには、いくつかの方法があります。

おそらく最も簡単な方法は、taskオブザーバブルにして ajax 呼び出しの結果として設定することです。この変更を考慮してバインディングを調整する必要がある場合があります。

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

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

より柔軟なオプションは、Taskオブジェクトに個別の初期化メソッドを追加し、タスクを設定する (初期化されていない) ことです。次に、ajax 呼び出しの結果として、初期化メソッドを呼び出して初期化します。もちろん、タスク オブジェクトの初期化コードを調整する必要があります。

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);
        }));
    };
}
于 2012-11-11T18:23:40.860 に答える