How to structure a single page app with knockout.js?

We are just starting down this path at work, and so are not quite sure what we’re doing. But here’s the idea we have.

The page should be composed of any number of “components,” possibly nested. Each component has a view model and one public method, renderTo(el), which essentially does

ko.applyBindings(viewModelForThisComponent, el)

It also could have the ability to render subcomponents.

Constructing or updating a component consists of giving it a model (e.g. JSON data from the server), from which it will derive the appropriate view model.

The app is then created by nesting a bunch of components, starting with a top-level application component.


Here is an example for a “hypothetical” book-managing application. The components are LibraryUI (displays a list of all book titles) and DetailsUI (a section of the app that displays details on a book).

function libraryBookViewModel(book) {
  return {
    title: ko.observable(book.title),
    showDetails: function () {
      var detailsUI = new BookDetailsUI(book);
      detailsUI.renderTo(document.getElementById("book-details"));
    }
  };
}

function detailsBookViewModel(book) {
  return {
    title: ko.observable(book.title),
    author: ko.observable(book.author),
    publisher: ko.observable(book.publisher)
  };
}

function LibraryUI(books) {
  var bookViewModels = books.map(libraryBookViewModel);
  var viewModel = {
    books: ko.observableArray(bookViewModels);
  };

  this.renderTo = function (el) {
    ko.applyBindings(viewModel, el);
  };
}

function BookDetailsUI(book) {
  var viewModel = detailsBookViewModel(book);

  this.renderTo = function (el) {
    ko.applyBindings(viewModel, el);
  };
}

Note how we could make the book details appear in a jQuery UI dialog, instead of in a singleton #book-details element, by changing the showDetails function to do

var dialogEl = document.createElement("div");
detailsUI.renderTo(dialogEl);
$(dialogEl).dialog();

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)