Я пытаюсь получить многопользовательский аккордеонный контроль для работы с нокаутом, но при добавлении панелей элементы, созданные с помощью привязок KO, не привязываются к аккордеонам в качестве новых панелей.
Код выглядит так:
<div data-bind="accordion: {collapsible: true, active: false, heightStyle: 'content'}, template: { name: 'queryTemplate', foreach: children }">
</div>
<script id="queryTemplate" type="text/html">
<h3>
<div>
<a href="#" data-bind="text: id"></a>
<span data-bind="text: name"></span>
<button data-bind="click: addNext">Add Next Item</button>
</div>
</h3>
<div >
<input data-bind="value: name"></input>
<input data-bind="value: id"></input>
<button data-bind="click: addSubitem">Add SubItem</button>
<hr/>
<div data-bind="accordion: {collapsible: true, active: false, heightStyle: 'content'}, template: { name: 'queryTemplate', foreach: children }">
</div>
</div>
</script>
<script>
ko.bindingHandlers.accordion = {
init: function(element, valueAccessor) {
var options = valueAccessor() || {};
setTimeout(function() {
$(element).accordion(options);
}, 0);
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function(){
$(element).accordion("destroy");
});
},
update: function(element, valueAccessor) {
var options = valueAccessor() || {},
existing = $(element).data("accordion");
//if it has been reinitialized and our model data changed, then need to recreate until they have a "refresh" method
if (existing) {
$(element).accordion("destroy").accordion(options);
//$(element).accordion("refresh");
}
}
};
function Item(id, name, parent) {
var self = this;
this.id = ko.observable(id);
this.name = ko.observable(name);
this.children = ko.observableArray();
this.addSubitem = function(){
self.children.push(new Item(self.children().length + 1, "", this));
}
this.parent = ko.observable(parent);
this.addNext = function(){parent.addSubitem()};
}
var model = new Item(0, "Top");
var tmp = new Item(1, "First", model);
tmp.children.push(new Item(0, "SubItem!", tmp));
model.children.push(tmp);
tmp = new Item(2, "Second", model);
tmp.children.push(new Item(0, "SubItem!", tmp));
model.children.push(tmp);
ko.applyBindings(model);
</script>
У меня сложилось впечатление, что это может быть связано с тем, как я создаю цикл шаблонов, но я нахожусь в этом с ума - спасибо, кто-нибудь
ЗАМЕТКА:
Я попытаюсь прояснить проблему, с которой я столкнулся - (здесь, на скрипке: http://jsfiddle.net/QChon/aUJFg/4/)
Аккордеон и вложенные гармоники загружаются правильно, следуя модели представления (элемент с массивом "children", содержащий снова объекты Item, которые должны длиться бесконечно).
Кнопка "Добавить следующий элемент" добавляет родственника к текущему элементу и, следовательно, к текущей панели аккордеона, а "Добавить SubItem" добавляет дочерние элементы к текущим дочерним элементам и, следовательно, к вложенной панели аккордеона под текущей панелью.
Проблема в том, что когда я нажимаю кнопки, правильные элементы html добавляются в правильные места (т.е. Как заголовок и как панель содержимого), но классы jquery и идентификаторы не привязаны к созданным элементам управления html, поэтому не отображают и не вести себя правильно как часть структуры аккордеона. Надеюсь, что это несколько прояснилось.
Проблема заключается в вашей настраиваемой функции привязки
Вы проверяете, является ли текущий элемент аккордеон, изучая атрибут data-accordion, который не существует даже на правильно инициализированном аккордеоне. Во-вторых, даже если он найдет этот атрибут, он попытается "воссоздать" аккордеон на неправильном уровне. Класс контейнера аккордеона является родительским родителем относительно элемента, который вы получаете в методе обновления.
Поэтому, если вы измените свою функцию из этого
var existing = $(element).data("accordion");
if (existing) $(element).accordion("destroy").accordion(options);
к этому
var existing = $(element).parent().parent().hasClass("ui-accordion");
if (existing) $(element).parent().parent().accordion('refresh');
он должен работать должным образом.