Skip to content
Create a gist now

Instantly share code, notes, and snippets.

Embed URL


Subversion checkout URL

You can clone with
Download ZIP
Knockout TreeView- A nice binding handler that accepts a dynamic tree of data, and displays a searchable and selectable tree-type list.
* {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: -moz-none;
-ms-user-select: none;
user-select: none;
font-family: "Segoe UI", "Helvetica", Arial, sans-serif;
.ko-treeview-container {
max-height: 300px;
overflow-y: auto;
overflow-x: hidden;
border: 1px solid #eee;
background-color: white;
border-radius: 3px;
padding-right: 7px;
padding-top: 5px;
.ko-treeview-container .navbar {
margin-right: 0px;
.ko-treeview-container > .ko-treeview-list {
padding: 0;
.ko-treeview-list {
list-style: none;
.ko-treeview-listitem {
line-height: 2em;
margin-top: 0px;
.ko-treeview-label {
-webkit-transition: all 250ms;
-moz-transition: all 250ms;
-ms-transition: all 250ms;
-o-transition: all 250ms;
cursor: pointer;
display: block;
margin-left: 5px;
width: 100%;
background-color: white;
color: #2980b9;
border-bottom: 1px solid #bdc3c7;
.ko-treeview-label:hover {
border-bottom-color: #2980b9;
.ko-treeview-cb {
-webkit-transition: all 250ms;
-moz-transition: all 250ms;
-ms-transition: all 250ms;
-o-transition: all 250ms;
float: right;
clear: both;
margin-top: 1em;
margin-left: 5px;
.ko-treeview-cb:checked {
margin-top: 1.5em;
.ko-treeview-cb:checked + label {
line-height: 50px;
font-weight: bold;
border-bottom-color: #27ae60;
font-size: 1.1em;
color: #27ae60;
<!DOCTYPE html>
<link href="" rel="stylesheet" type="text/css" />
<link href="" rel="stylesheet" type="text/css" />
<link href="treeview.css" rel="stylesheet" type="text/css" />
<script src=""></script>
<script src="treeview.js"></script>
<meta charset=utf-8 />
<title>Knockout TreeView</title>
<div data-bind="treeView:{title:'Some Title',selected:selectedNodes, data:data}">
<h4>Selected Nodes</h4>
<ul data-bind="foreach: selectedNodes">
<li data-bind="text: $data"></li>
ko.bindingHandlers.treeView = {
createNodes: function(rootElement, options){
var rootTmpl = '<script id="ko-treeview-root-tmpl"><div class="navbar"><p class="brand" data-bind="text:$data.title">Title</p><div class="container"><form class="navbar-form pull-right col-sm-4"><div class="input-append"><input class="span4" type="text" placeholder="Search" data-bind="value:$, valueUpdate: \'afterkeydown\'"/><span class="add-on"><i class="icon-search"></i></span></div></form></div></div><ul class="ko-treeview-list" data-bind="template:{foreach:$,name:\'ko-treeview-node-tmpl\'}"></ul></script>';
var nodeTmpl = '<script id="ko-treeview-node-tmpl"><li class="ko-treeview-listitem"><div data-bind="template:{name:\'ko-treeview-item-tmpl\',data:$data}"></div><ul class="ko-treeview-list" data-bind="template:{name:\'ko-treeview-node-tmpl\',foreach:$data[$root.childNode]}"></div></li></script>';
var itemTmpl ='<script id="ko-treeview-item-tmpl"><div data-bind="visible:$data[$root.label].indexOf($ > -1"><input type="checkbox" class="ko-treeview-cb" data-bind="checked: $root.selected, attr:{value:$data[$root.label], id:$data[$root.label]}" /><label class="ko-treeview-label" data-bind="text:$data[$root.label], attr:{for:$data[$root.label]}"></label></div></script>'
//append templates
document.body.insertAdjacentHTML('beforeend', rootTmpl);
document.body.insertAdjacentHTML('beforeend', nodeTmpl);
document.body.insertAdjacentHTML('beforeend', itemTmpl);
//apply first binding
ko.applyBindingsToNode(rootElement, {template:{name:"ko-treeview-root-tmpl"}},options);
init: function(element, valueAccessor) {
//style element
element.className = "ko-treeview-container";
//extend options with search
var options = valueAccessor(); = ko.observable("");
//set default data values
if(!options.label) options.label = 'id';
if(!options.childNode) options.childNode = 'children';
//create the tree
//let this handler control its descendants.
return { controlsDescendantBindings: true };
function vm(){
this.selectedNodes = ko.observableArray([]); = ko.observableArray([
id:"Level 1",
{id:"Level 1-1",children:[
{id:"Level 1-1-1",children:[
{id:"Level 1-1-1-1"}
{id:"Level 1-2"},
id:"Level 2",
{id:"Level 2-1",children:[
{id:"Level 2-1-1"}
{id:"Level 2-2"},
var myVM = new vm();

@bringking Very nice! Is it possible to give the data a more friendly title attribute along with the id?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.