Несколько вложенных JQuery UI Accordion, созданных с помощью шаблона Knockout, не связываются правильно

0

Я пытаюсь получить многопользовательский аккордеонный контроль для работы с нокаутом, но при добавлении панелей элементы, созданные с помощью привязок 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>&nbsp;
            <span data-bind="text: name"></span>&nbsp;
            <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, поэтому не отображают и не вести себя правильно как часть структуры аккордеона. Надеюсь, что это несколько прояснилось.

  • 0
    Нужна лучшая идея о том, что идет не так или какую ошибку вы получаете ...
  • 0
    Привет - я редактировал вышеупомянутое, пытаясь прояснить проблему; Спасибо!
Теги:
knockout.js
accordion

1 ответ

0
Лучший ответ

Проблема заключается в вашей настраиваемой функции привязки

Вы проверяете, является ли текущий элемент аккордеон, изучая атрибут 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');

он должен работать должным образом.

http://jsfiddle.net/M9222/1/

  • 0
    Большое спасибо!! Я основывал свой код на примерах, которые, похоже, работают для других, но, отлаживая, я также заметил, что атрибутов там не было, и связывание происходило на неправильном уровне. Спасибо за исправление, теперь оно отлично работает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню