Knockout и JSTree не рендерится должным образом - PullRequest
2 голосов
/ 03 января 2012

Я использую KnockoutJS на своей странице и пытаюсь заполнить DOM для JsTree, но JsTree неправильно определяет листья и применяет какие-либо изменения в коде листьев (или папок), которые заполняет KnockoutJs. Есть ли способ сообщить JsTree, что появились новые данные и что нужно все переоценить? Скрипт в начале страницы

$(document).ready(function() {

        function treeNode(data) {
            var self = this;
            self.id = ko.observable(data.ID);
            self.name = ko.observable(data.Name);
        }

        function partsViewModel() {
            var self = this;
            self.partTypes = ko.observableArray([]);
            self.selectedPartType = ko.observable();
            self.selectedPartType = ko.observable();

            $.getJSON("/PartKO/PartTypes", function(allData) {
                var mappedPartTypes = $.map(allData, function(item) { return new treeNode(item); });
                self.partTypes(mappedPartTypes);
            });

            $("#navigation").jstree({
                "themes": { "theme": "classic" },
                "plugins": ["themes", "html_data"]
            });
        }

        ko.applyBindings(new partsViewModel());

    });

HTML

ul id="navigation" class="treeview" data-bind="foreach: partTypes">
        <li>
            <a href="#" data-bind="text:name"></a>
        </li>
    </ul>

1 Ответ

5 голосов
/ 04 января 2012

Вам необходимо вызвать .jstree после заполнения списка, поэтому переместите вызов в конец обратного вызова $.getJSON.

Также navigation должен быть контейнером, содержащим <ul>элемент, а не сам список.

Измените partsViewModel функцию на:

function partsViewModel() {
    var self = this;
    self.partTypes = ko.observableArray([]);
    self.selectedPartType = ko.observable();
    self.selectedPartType = ko.observable();

    $.getJSON("/PartKO/PartTypes", function(allData) {
      var mappedPartTypes = $.map(allData, function(item) { return new treeNode(item); });
      self.partTypes(mappedPartTypes);

      $("#navigation").jstree({
        "themes": { "theme": "classic" },
        "plugins": ["themes", "html_data"]
      });
    });
}

И ваш HTML-код:

<div id="navigation">
  <ul class="treeview" data-bind="foreach: partTypes">
    <li>
        <a href="#" data-bind="text:name"></a>
    </li>
  </ul>
</div>

ЗДЕСЬ - упрощенный пример.

Обновление:

Если вы хотите обновлять дерево каждый раз при изменении <ul>, вы можете использовать Knockout's .afterRender обратный вызов.Это будет вызвано после обновления DOM.Вы не можете использовать .subscribe(), потому что он вызывается до изменения DOM.

Вставьте это в partsViewModel и удалите часть .jstree из обратного вызова .getJSON:

    self.redrawTree = function() {
        $("#navigation").jstree({
            "themes": {
                "theme": "classic"
            },
            "plugins": ["themes", "html_data"]
        });
    };

И изменить HTML на:

<div id="navigation">
  <ul class="treeview" data-bind="foreach: { data: partTypes, afterRender: redrawTree }">
    <li>
      <a href="#" data-bind="text:name"></a>
    </li>
  </ul>
</div>
...