JSFiddle - React, Tailwind, and code Playground

by AlexandrAbakumov

HTML

<script src="https://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.debug.js"></script>
<div id="ko-root">
  <!-- ko withProperties: { book: $root.getBook() } -->
    <!-- ko foreach: {data: book.pages, as: 'page'} -->
      <span data-bind="text: page.pageName" ></span>
      <button data-bind="click: book.bookClicked" >Press me</button>
      <!-- ko foreach: {data: page.categories, as: 'category'} -->
        <span data-bind="text: category.categoryName" ></span>
        <button data-bind="click: page.pageClicked" >Press me</button>
        <!-- etc -->
      <!-- /ko -->
    <!-- /ko -->
  <!-- /ko -->
<div>

JavaScript

// http://knockoutjs.com/documentation/custom-bindings-controlling-descendant-bindings.html
ko.bindingHandlers.withProperties = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // Make a modified binding context, with a extra properties, and apply it to descendant elements
        var innerBindingContext = bindingContext.extend(valueAccessor);
        ko.applyBindingsToDescendants(innerBindingContext, element);
 
        // Also tell KO *not* to bind the descendants itself, otherwise they will be bound twice
        return { controlsDescendantBindings: true };
    }
};

var viewModel = {
	getBook : function() {
  	return {
      pages: [{
        pageName: 'Page 1',
        categories: [{
        	categoryName: 'Category 1'
        }],
        pageClicked: function () {
          alert('pageClicked() called.');
        }
      }],
      bookClicked: function () {
        alert('bookClicked() called.');
      }
    };
  }
};

ko.applyBindings(viewModel, document.getElementById('ko-root'));