title: Updating a JSTree using Knockout Custom Binding
body: <p>I'm trying to create a JSTree interface that uses Knockout JS as the viewmodel for the project.</p>
  
  <p>I would like to be able to create/rename/delete nodes via the viewmodel where the JSTree 'building' happens in a custombinding.  I am having a hard time figuring out how to access the jstree in my viewmodel (while keeping the ui decoupled) so I can CRUD the nodes.</p>
  
  <p>I obviously don't want to push new objects into an array but this was done as a proof of concept that the observableArray([]) can be used for the data.</p>
  
  <p><a href="http://jsfiddle.net/ascendantofrain/76cco3cs/41/" rel="nofollow">http://jsfiddle.net/ascendantofrain/76cco3cs/41/</a></p>
  
  <h2>HTML</h2>
  
  <pre><code>&lt;div class="wrapper"&gt;
  
      &lt;div class="button-wrapper"&gt;
          &lt;button type="button" class="btn btn-success btn-sm" data-bind="click: $root.createFolder"&gt;Create Folder&lt;/button&gt;
          &lt;button type="button" class="btn btn-success btn-sm" data-bind="click: $root.createFile"&gt;Create File&lt;/button&gt;
          &lt;button type="button" class="btn btn-warning btn-sm" data-bind="click: $root.rename"&gt;Rename&lt;/button&gt;
          &lt;button type="button" class="btn btn-danger btn-sm" data-bind="click: $root.delete"&gt;Delete&lt;/button&gt;
      &lt;/div&gt;
      &lt;pre data-bind="text: treeData"&gt;&lt;/pre&gt;
  
      &lt;div id="jstree_demo_div" data-bind="jstree: { data: treeData }"&gt;&lt;/div&gt;
  
      &lt;!-- &lt;div id="jstree_demo_dev_attributes"&gt;
          &lt;ul&gt;
            &lt;li&gt;Attribute Reporting Group
              &lt;ul&gt;
                &lt;li&gt;Invoice Dates&lt;/li&gt;
              &lt;/ul&gt;
            &lt;/li&gt;
          &lt;/ul&gt;
      &lt;/div&gt; --&gt;
  
  &lt;/div&gt;
  </code></pre>
  
  <h2>KNOCKOUT JS</h2>
  
  <pre><code>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());
  </code></pre>