我正在尝试创建一个使用Knockout JS作为项目视图模型的JSTree接口。
我希望能够通过viewmodel创建/重命名/删除节点,其中JSTree'building'在自定义绑定中发生。我很难弄清楚如何在我的viewmodel中访问jstree(同时保持ui解耦),所以我可以CRUD节点。
我显然不想将新对象推送到数组中,但这是作为概念证明,observableArray([])可以用于数据。
http://jsfiddle.net/ascendantofrain/76cco3cs/41/
<div class="wrapper">
<div class="button-wrapper">
<button type="button" class="btn btn-success btn-sm" data-bind="click: $root.createFolder">Create Folder</button>
<button type="button" class="btn btn-success btn-sm" data-bind="click: $root.createFile">Create File</button>
<button type="button" class="btn btn-warning btn-sm" data-bind="click: $root.rename">Rename</button>
<button type="button" class="btn btn-danger btn-sm" data-bind="click: $root.delete">Delete</button>
</div>
<pre data-bind="text: treeData"></pre>
<div id="jstree_demo_div" data-bind="jstree: { data: treeData }"></div>
<!-- <div id="jstree_demo_dev_attributes">
<ul>
<li>Attribute Reporting Group
<ul>
<li>Invoice Dates</li>
</ul>
</li>
</ul>
</div> -->
</div>
function tree() {
var self = this;
self.createFolder = function (data) {
self.treeData.push({
'id': 'iPhone',
'parent': 'device',
'text': 'iPhone',
'type': 'default'
});
};
self.createFile = function (data) {
self.treeData.push({
'id': 'ios8',
'parent': 'iPhone',
'text': 'iOS 8',
'type': 'file'
});
};
self.rename = function (data) {
};
self.delete = function (data) {
};
self.treeData = ko.observableArray([
{ 'id': 'animal', 'parent': '#', 'text': 'Animals' },
{ 'id': 'device', 'parent': '#', 'text': 'Devices' },
{ 'id': 'dog', 'parent': 'animal', 'text': 'Dogs' }
]);
};
ko.bindingHandlers.jstree = {
buildTree: function (element, treeData) {
$(element).jstree('destroy');
$(element).jstree({
'core': {
'animation': 0,
'check_callback': true,
'data': treeData
},
'types': {
'#': {
'max_depth': 4,
'valid_children': ['root']
},
'level_1': {
'valid_children': ['default']
},
'level_2': {
'valid_children': ['file']
},
'file': {
'icon': 'glyphicon glyphicon-file'
}
},
'plugins': [
'search',
'state',
'types',
'wholerow',
'unique'
]
});
},
update: function (element, valueAccessor) {
var treeData = ko.unwrap(valueAccessor());
ko.bindingHandlers.jstree.buildTree(element, treeData.data());
}
};
ko.applyBindings(new tree());
答案 0 :(得分:6)
现在为时已晚,但请看一下:http://jsfiddle.net/u4a7k5zu/20/
这是你小提琴的修改版。不确定这是否是你要找的。你可能已经弄明白了。也许它可以帮助别人。
FIDDLE CODE:
function tree() {
var self = this;
//display actions in fiddle
self.consoleLine = "<p class=\"console-line\"></p>";
self.consoleLog = function (text) {
$("#console-log").append($(self.consoleLine).html(text));
};
self.clearConsoleLog = function () {
$("#console-log").html('');
};
self.tree = $('#jstree_demo_div'); //get jstree div
self.isNodeSelected = ko.observable(false);
self.selectedNode = ko.observable({});
//deselect all nodes
self.deselectAllNodes = function () {
self.tree.jstree('deselect_all');
}
//keep track of selected node
self.tree.on("changed.jstree", function (e, data) {
var node = self.tree.jstree().get_selected(true)[0]; //get current selected node
if (typeof node !== 'undefined') {
self.isNodeSelected(true);
self.selectedNode(node);
self.consoleLog('selected node id: ' + node.id + ', type: ' + node.type);
} else {
self.isNodeSelected(false);
}
});
self.createFolderNode = function (data) {
//node can be created on a preselected node or pass # to create a root node
var node;
var data;
if (self.isNodeSelected())
{
node = self.selectedNode();
data = {'id': Math.floor((Math.random() * 10000) + 1),
'text': 'iPhone', 'type': 'folder'};
}
else
{
node = '#';
data = {'id': Math.floor((Math.random() * 100000) + 1),
'parent': '#',
'text': 'New Root Node',
'type' : 'root'
};
}
//create node
var id = self.tree.jstree("create_node", node, data, 'last');
self.tree.jstree('open_node', node);
self.tree.jstree('edit', id);
};
self.createFileNode = function (data) {
//Below code only allows files to be created within folders.
//Structure it as per createFolder method to create files at root
var data = {
'id': Math.floor((Math.random() * 100000) + 1),
'text': 'iOS 8',
'type': 'file'
}
//create file node
var id = self.tree.jstree("create_node", self.selectedNode(), data, 'last');
self.tree.jstree('open_node', self.selectedNode());
self.tree.jstree('edit', id);
};
self.renameNode = function (data) {
if(self.isNodeSelected()){
self.tree.jstree('edit', self.selectedNode());
}
else{
alert('please select a node to rename!');
}
};
self.deleteNode = function (data) {
if(self.isNodeSelected()){
self.tree.jstree('delete_node', self.selectedNode());
}
else{
alert('please select a node to delete!');
}
};
self.treeData = ko.observableArray([{
'id': 1,
'parent': '#',
'text': 'Animals',
'type': '#'
}, {
'id': 2,
'parent': '#',
'text': 'Devices',
'type' : '#'
}, {
'id': 'dog',
'parent': 1,
'text': 'Dogs',
'type' : 'folder'
}]);
};
ko.bindingHandlers.jstree = {
buildTree: function (element, treeData) {
$(element).jstree('destroy');
$(element).jstree({
'core': {
'animation': 0,
'check_callback': true,
'data': treeData
},
'types': {
'#': {
'max_children': 10,
'max_depth': 10,
'valid_children': ['root', 'folder','file']
},
'folder': {
'valid_children': ['folder','file']
},
'file': {
'icon': 'glyphicon glyphicon-file',
'max_depth': 0
}
},
'plugins': [
'search',
'state',
'types',
'wholerow']
});
},
update: function (element, valueAccessor) {
var treeData = ko.unwrap(valueAccessor());
ko.bindingHandlers.jstree.buildTree(element, treeData.data());
}
};
ko.applyBindings(new tree());