JSFiddle - React, Tailwind, and code Playground

by ksumarine

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jstree/3.0.9/jstree.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.0.9/themes/default/style.min.css">
<span data-bind="html: name"></span><br />
<input type="text" data-bind="value: name" />
<br /><br />


<div id="tree">
    <ul>
        <li>
            <a href="#" data-bind="html: name"></a>
            <ul data-bind="foreach: children, afterRender: redrawTree">
                <li data-bind="attr: {id: name}">
                    <a data-bind="html: name"></a>
                    <ul data-bind="foreach: children">
                       <li data-bind="attr: {id: name}">
                            <a data-bind="html: name"></a>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>

JavaScript

var DataViewModel = function(data) {
	ko.mapping.fromJS(data, {}, this);
};
DataViewModel.prototype.redrawTree = function() {
    console.log('refresh');
	$("#tree").jstree('refresh');
};

var viewModel = new DataViewModel({
	name: 'goal',
	children: [{
		name: 'subgoal',
		children: [{
			name: 'activity'
		}]
	}]
});
ko.applyBindings(viewModel)

$("#tree").jstree({
	'themes': {
		'theme': 'classic'
	},
	'contextmenu': {
		'items': function($node) {
			var tree = $('#tree').jstree(true);
			return {
				'Create': {
					'separator_before': false,
					'separator_after': false,
					'label': 'Create',
					'action': function(obj) {
						$node = tree.create_node($node);
						tree.edit($node);
					}
				},
				'Rename': {
					'separator_before': false,
					'separator_after': false,
					'label': 'Rename',
					'action': function(obj) {
						tree.edit($node);
					}
				},
				'Remove': {
					'separator_before': false,
					'separator_after': false,
					'label': 'Remove',
					'action': function(obj) {
						tree.delete_node($node);
					}
				}
			};
		}
	},
	'plugins': ['contextmenu']
});