Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am mostly wondering how to organize things like modal windows, and dynamic pages like profiles. Should the viewModel only contain one profile view or contain all profiles loaded? This here just doesnt seem very "clean".

viewModel = {   profile: ko.observableArray([     new ProfileViewModel()     //... any others loaded   ]) , createPostModal: {     input: ko.observable()   , submit: //do something to submit...   } }  <div data-bind="foreach: profile"><!-- profile html --></div> <div data-bind="with: createPostModal"></div> 

This way doesn't seem very consistent. Is there anybody who has built a single page app with knockout that can offer some advice? Code samples would be appreciated.

like image 352
sdfadfaasd Avatar asked Feb 11 '12 17:02

sdfadfaasd


2 Answers

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(); 
like image 78
Domenic Avatar answered Sep 30 '22 18:09

Domenic


There are 3 frameworks out there that help with creating SPAs using Knockoutjs.

  • Durandal
  • Pagerjs
  • KnockBack

I have used Durandal and I really like it. Easy to use and has a lot of nice configurations so you can plug-in your own implementations. Also, Durandal is created by the same creator of Caliburn which was an very popular framework for building Silverlight/WPF applications.

like image 31
Evan Larsen Avatar answered Sep 30 '22 18:09

Evan Larsen