Как получить базовую коллекцию Backbone в Knockback CollectionObservable из объекта контекста $data с вложенными шаблонами

Взяв следующий фрагмент кода в качестве быстрого примера:

var Animal = Backbone.Model.extend();
var Zoo = Backbone.Collection.extend({ model: Animal });

var tiger = new Animal({ name: "tiger" });
var zoo = new Zoo(tiger);

var viewModel = {
    tiger: kb.viewModel(tiger);
    zoo: kb.collectionObservable(zoo);
}

ko.applyBindings(viewModel);

из контекста $data вы можете получить ссылку на модель тигра:

tiger === $data.tiger().__kb.object;

или же

tiger === $data.zoo()[0].__kb.object;

и я предполагаю, что она существует где-то в этой функции зависимых от наблюдаемых, но я не могу найти ссылку на исходную коллекцию Backbone

$data.zoo

У кого-нибудь есть идеи, как добраться до оригинальной коллекции Backbone?

Кроме того, бонусные баллы, если вы можете рассказать мне о любом способе получения в Backbone Collection, если вместо этого используется viewmodel:

viewModel = kb.collectionObservable(zoo)

проблема в том, что $data содержит результаты оцененной функции depenndantObservable.


РЕДАКТИРОВАТЬ После получения совершенно правильного ответа на вопрос выше, я понял, что моя проблема возникает только в моем более сложном связывании с вложенными шаблонами:

Шаблоны выглядят так:

    <!-- outer template -->
    <script type="text/html" id="tmpl-outer">
        <button data-bind="click: $root.outerContext">Outer Context</button>
        <div data-bind="template: { name: 'tmpl-inner', data: collection }"></div>
    </script>

    <!-- inner template -->
    <script type="text/html" id="tmpl-inner">
        <button data-bind="click: $root.innerContext">Inner Context</button>
        <div data-bind="foreach: $data">
            <button data-bind="click: $root.modelContext">Model Context</button>
        </div>
    </script>

Модель и вид-модель:

var model = new Backbone.Model();
var collection = new Backbone.Collection(model);

var viewModel = {
    collection: kb.collectionObservable(collection),
    outerContext: function (data) {
        console.log(data.collection.collection() === collection);
    },
    innerContext: function (data) {
        console.log("??????? === collection");
    },
    modelContext: function (data) {
        console.log(data.model() === model);
    }
};

ko.applyBindings(viewModel);

И наконец, где-нибудь все отрендерить

<body>
    <div data-bind="template: { name: 'tmpl-outer' }"></div>
</body>

Итак, мой первоначальный вопрос, для которого я чрезмерно упростил свой пример, должен был звучать так: как мне получить базовую коллекцию в строке:

console.log("??????? === collection");

Похоже, что коллекция в этом контексте была преобразована в простой наблюдаемый массив KnockOut - кажется, нет никаких важных свойств KnockBack.

2 ответа

Решение

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

Теперь у модели представления есть эта функция:

doSomethingWithUnderlyingCollection: function(collectionName, parentContext) {
    var underlyingCollection = parentContext.model().get(collectionName);

    // do something with the underlying collection here, e.g. add a model.
}

А затем вызвать метод из шаблона:

<button data-bind="click: function() { $root.doSomethingWithUnderlyingCollection('MyCollection', $parent); }">Add</button>

Вы можете получить базовую коллекцию / модель, используя геттеры на экземплярах kb.CollectionObservable а также kb.ViewModel,

var collection = new Backbone.Collection(),
    view_models = kb.collectionObservable(collection),
    reference = view_models.collection();

console.log(collection === reference);

Вы можете сделать то же самое с экземплярами kb.viewModel

var model = new Backbone.Model({ id : 1 }),
    view_model = kb.viewModel(model),
    reference = view_model.model();

console.log(model === reference);

Вы можете получить доступ к коллекции / модели, а также $data вызывая геттеры в привязках данных, хотя я действительно не вижу никакой необходимости делать это, если вы используете фабрику view_models для коллекции, позволяющую вам определить любое количество определенных вычисляемых / наблюдаемых для каждого виртуального компьютера.

var model = new Backbone.Model({ id : 1 });

var collection = new Backbone.Collection(model);

var AnimalViewModel = kb.ViewModel.extend({
    constructor: function(model) {
        kb.ViewModel.prototype.constructor.call(this, model, {});
        return this;

        // Custom code per vm created
    }
});

var view_model = {
    zoo : kb.collectionObservable(collection, {
        view_model : AnimalViewModel
    });
}
Другие вопросы по тегам