Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
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();

This comment has been minimized.

Show comment Hide comment

bringking Jan 12, 2014


bringking commented Jan 12, 2014

This comment has been minimized.

Show comment Hide comment

jotosmurf May 30, 2014

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

@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