Вам необходимо вызвать .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>