Knockout.js可观察的动态绑定

时间:2013-06-13 21:02:10

标签: javascript dynamic knockout.js ko.observablearray

我正在尝试利用knockout创建一个可编辑的表格。我有一个JSON对象,它包含标题和表数据的集合。该表需要使用任何对象构建。它将循环遍历JSON对象以创建ko.observableArray和ko.observables以填充它。我已经能够做到这一点。我的问题是ko.observables不是数据绑定的。

以下是我的JavaScript代码片段:

EditableTableVM.prototype.load = function() {
    this.headings = this.buildKO_ObservableArray(new Heading(), this.dataRepo.HEADINGS);
    this.listings = this.buildKO_ObservableArray(new Listing(), this.dataRepo.LISTINGS);
}

/*
 * Dynamically creates a ko.observableArray from a JS array
 * Params: JSClass - new instance of a class
 * Params: baseArray - array of objects to create the observable array
 * Returns: Observable arary of JS object with ko.observables
 */
EditableTableVM.prototype.buildKO_ObservableArray = function(JSClass, baseArray) {
    var newArray = ko.observableArray([]);

    for(var i = 0, j = baseArray.length; i < j; i++) {
        var baseObj = baseArray[i];

        //new class is the class with ko.observables properties
        var newClass = this.buildKO_Observable(JSClass, baseObj);
        newArray.push(newClass);
    }

    return newArray;
}

/*
 * Dynamically create ko.observable from properties in an object
 * Params: JSClass - new instance of a class
 * Params: jsObject - object to created observables with
 * Returns: JS object with ko.observables
 */
EditableTableVM.prototype.buildKO_Observable = function(JSClass, jsObj) {
    for (var key in jsObj) {
        if (jsObj.hasOwnProperty(key)) {
            JSClass[key] = ko.observable(jsObj[key]);
        }
    }

    return JSClass;
}

这是我的小提琴http://jsfiddle.net/breck421/YFNLX/,正如我前面所描述的那样。

我不确定我想要做的事情是否可能,并且真的很感激另一双眼睛。

谢谢,

约旦

3 个答案:

答案 0 :(得分:1)

像这样(fiddle

使用Javascript:

var DynamicObservable = function(data) {
    for (var key in data) {
        this[key] = ko.observable(data[key]);
    }
};

var ViewModel = function(data) {
    var self = this;
    self.items = ko.observableArray(ko.utils.arrayMap(data, function(i) {
        return new DynamicObservable(i);
    }));
    self.columns = ko.observableArray();
    for (var key in data[0]) {
        self.columns.push(key);
    }
};

HTML

<table>
    <thead>
        <tr data-bind="foreach: columns">
            <th data-bind="text: $data"></th>
        </tr>
    </thead>
    <tbody data-bind="foreach: { data: items, as: 'item'}">
        <tr data-bind="foreach: $parent.columns">
            <td><input data-bind="value: item[$data]" /></td>
        </tr>
    </tbody>
</table>

如果您希望能够创建新对象,那么您肯定可以改进这一点。只需存储“列”并使用它来初始化一个新类型,但值为空。

注意,检查hasOwnProperty是没用的。由于您的数据来自JSON,因此它始终是真的。

答案 1 :(得分:1)

您遇到的问题是,当您将JSON映射到支持knockout的视图模型时,您无法正确处理具有数组的子项。你的映射不够深入。

如果您检查以下内容:

EditableTableVM.listings()[0].LISTING()[0];

你会看到该对象的属性只是值,而不是ko.observables。

我没有尝试从头开始构建这个映射,而是建议使用其中一个淘汰映射插件:这里的淘汰映射插件:https://github.com/SteveSanderson/knockout.mapping及其文档:http://knockoutjs.com/documentation/plugins-mapping.html或更新Knockout ViewModel插件在这里:http://coderenaissance.github.io/knockout.viewmodel/

我已经使用淘汰映射插件更新了您的小提琴:http://jsfiddle.net/rrahlf/YFNLX/2/现在您的值正确绑定。

祝你好运!

答案 2 :(得分:1)

您似乎想要使用http://coderenaissance.github.io/knockout.viewmodel/

之类的内容
EditableTableVM.prototype.load = function () {
    this.headings = ko.viewmodel.fromModel(this.dataRepo.HEADINGS);
    this.listings = ko.viewmodel.fromModel(this.dataRepo.LISTINGS);
}

http://jsfiddle.net/mbest/YFNLX/3/