绑定和ko.toJSON无法按预期工作

时间:2013-04-24 22:19:19

标签: jquery knockout.js

我正在学习KO并试图创建一个简单的列表项添加/删除。但我有以下问题。

Q1:如果您单击添加而不输入名称,则您刚添加的项目将以result作为名称。为什么以及如何在允许空作为有效输入时阻止它?

Q2:我想使用<pre>标签来显示当前视图模型的JSON,但它没有显示任何内容。但按钮显示了一些东西。 我想出了这个。我需要使用ko.toJSON($data, null, 4)

问题3:它与Q2有关,按钮显示了一些内容,但它显示的内容似乎很奇怪。输入几个项目后,单击debug按钮。您将看到视图模型中的所有项目都被您更改的最后一项替换。

这是fiddle

CSS:

input[type=text], select {
    width:100px;
}

JS:

function foodie() {
    this.name;
    this.food;
}

function foodieApp() {
    var self = this;
    self.foodies = ko.observableArray();
    self.foodieToAdd = ko.observable(new foodie());

    self.addFoodie = function () {
        this.foodies.push(this.foodieToAdd());
    };

    self.delFoodie = function (foodieToDel) {
        self.foodies.remove(foodieToDel);
    };

    self.debug = function () {
        alert(ko.toJSON(self, null, 4));
    };
}

var app = new foodieApp();
ko.applyBindings(app);

HTML:

<table>
    <thead>
        <tr>
            <td>Foodie's Name
                <br/>
                <input type=text data-bind='value: foodieToAdd().name' />
            </td>
            <td>Foodie's Food
                <br/>
                <select data-bind='value: foodieToAdd().food'>
                    <option value=apple>Apple</option>
                    <option value=banana>Banana</option>
                    <option value=cherry>Cherry</option>
                </select>
            </td>
            <td>
                <input type=button value=Add data-bind='click: addFoodie' />
            </td>
        </tr>
    </thead>
    <tbody data-bind='foreach: foodies'>
        <tr>
            <td>
                <input type=text data-bind='value: name' />
            </td>
            <td>
                <select data-bind='value: food'>
                    <option value=apple data-bind>Apple</option>
                    <option value=banana>Banana</option>
                    <option value=cherry>Cherry</option>
                </select>
            </td>
            <td>
                <input type=button value=del data-bind='click: $parent.delFoodie' />
            </td>
        </tr>
    </tbody>
</table>
<input type=button value=debug data-bind='click: debug' />
<!-- why the following <pre> tag is empty? -->
<pre data-bind='text: ko.toJSON(app, null, 4)'></pre>

1 个答案:

答案 0 :(得分:2)

这是一个更新的小提琴:http://jsfiddle.net/jearles/TgD6a/3/

-

  • Q1:您没有初始化foodie对象
  • Q2:app不是ViewModel的一部分 - 它是ViewModel。使用$root访问顶级ViewModel
  • 问题3:这与您定义foodieToAdd的方式有关。基本上你只创建一个实例,因此Knockout不断地反复添加相同的对象。因为你没有可观察的属性,所以敲门不会更新UI。

在我的小提琴中,我改变了foodieToAdd的定义方式。它现在只是一个标准对象,具有两个可观察的属性。当您单击add时,它会克隆foodieToAdd以在observableArray中创建新条目。

编辑:请参阅下面的评论,了解为什么淘汰赛正在升级result

-

function foodie(foodie) {
    this.name = ko.observable(foodie ? foodie.name() : '');
    this.food = ko.observable(foodie ? foodie.food() : '');
}

function foodieApp() {
    var self = this;
    self.foodies = ko.observableArray();
    self.foodieToAdd = new foodie();

    self.addFoodie = function () {
        this.foodies.push(new foodie(this.foodieToAdd));
    };

    self.delFoodie = function (foodieToDel) {
        self.foodies.remove(foodieToDel);
    };

    self.debug = function () {
        alert(ko.toJSON(self, null, 4));
    };
}

var app = new foodieApp();
ko.applyBindings(app);