Knockout.js динамическое связывание наблюдаемых

Я пытаюсь использовать нокаут для создания редактируемой таблицы. У меня есть объект 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;
}

Вот мой Fiddle http://jsfiddle.net/breck421/YFNLX/ с которым он работает до точки, которую я описал ранее.

Я не уверен, возможно ли то, что я пытаюсь сделать, или нет, и я был бы очень признателен за это.

Спасибо,

Иордания

3 ответа

Решение

Проблема, с которой вы сталкиваетесь, заключается в том, что, когда вы отображаете свой JSON на модели представления с поддержкой выбивки, вы неправильно обрабатываете детей с массивами. Ваше отображение не идет достаточно глубоко.

Если вы проверите следующее:

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/ и теперь ваши значения связываются правильно.

Удачи!

Как то так ( скрипка)

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, они всегда будут верными.

Похоже, вы хотите использовать что-то вроде 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/

Другие вопросы по тегам