Bind knockout view model to Bootstrap Tree View

2.1k views Asked by At

I am trying to get Knockout and a Bootstrap-TreeView to work together. (The component: https://github.com/jonmiles/bootstrap-treeview)

At the moment, I'm passing the JSON from an API call to the constructor of the View Model. This will change later but for simplicity, I'm doing this.

What I need then is to bind click events to each node. So if I click the root node, nothing happens, click a folder, and I can get a list of all it's direct child text values (Just alert them for now), and if I click a file node, I alert the 'data' value from that node.

Here's a fiddle to see what I have done so far.

https://jsfiddle.net/Cralis/h15n2tp7/

My View Model simply initialises with the json data. And then a computed in the view model does the setup of the Tree View.

// Create the View Model.
var ViewModel = function(jsonData) {
  var self = this;
  self.MyData = ko.observable(jsonData);

  ko.computed(function() {
    $('#tree').treeview({
        data: self.MyData()
      })
      .on('nodeSelected', function(event, data) {
        if (data.nodeLevel == 2) { // Are we clicking a File?
          alert("Clicked a File. Data: " + data.data)

        }
        else
        if(data.nodeLevel == 1) { // We're clicking a folder.
           alert("Clicked a folder. Would like to somehow alert a list of all child node text values.")
        }
      });
  })
}

// Create the View Model and initialise with initial data 
var vm = new ViewModel(getTree());

// Bind.
ko.applyBindings(vm, document.getElementById("bindSection"));

This works, but I don't think I'm using Knockout much. That's because my click events are in my javascript, and my Knockout view model doesn't really have any control.

How can I allow Knockout to 'see' the click events. So, onclick of a node, a knockout computed (I think?) fires and I can then control the UI based on bind events.

Outside of this, I have a DIV which shows a list of files. What I was was that when a folder level node gets selected, I can populate that div with all the 'text' values from the children of that selected folder node.

Any pointers in how I can achieve this would be amazing. I'm just not sure how I can get data-bind="click... to the nodes, which can then run the code that's currently in the 'onclick' in my fiddle.

1

There are 1 answers

9
Adam Wolski On BEST ANSWER

I've updated your fiddle with a custom binding: https://jsfiddle.net/h15n2tp7/2/

As I already posted here in this question: add-data-bind-property-to-a...

I think this is the best way do it. The problem here is the synchronization between 1) fetching JSON 2) applying bindings 3) creating DOM elements. Creating custom binding lets you do that easily without much of messy code. In your case, when a getTree function is done via $.get, you need to create a view model in .done function, and apply bindings after that. So the provided fiddle will change a bit, but the idea is the same. Note, that you don't need any observables (if the tree data does not change while the app is running). If it does change though, make sure that you implement update function in a custom binding (knockout custom binding reference).