Как получить базовую коллекцию 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
});
}