EzDevInfo.com

knockout.js interview questions

Top knockout.js frequently asked interview questions

Can you call ko.applyBindings to bind a partial view?

I'm using KnockoutJS and have a main view and view model. I want a dialog (the jQuery UI one) to popup with another view which a separate child view model to be bound to.

The HTML for the dialog content is retreived using AJAX so I want to be able to call ko.applyBindings once the request has completed, and I want to bind the child view model to just the portion of the HTML loaded via ajax inside the dialog div.

Is this actually possible or do I need to load ALL my views and view models when the page initially loads and then call ko.applyBindings once?


Source: (StackOverflow)

How to clear/remove observable bindings in Knockout.js?

I'm building functionality onto a webpage which the user can perform multiple times. Through the user's action, an object/model is created and applied to HTML using ko.applyBindings().

The data-bound HTML is created through jQuery templates.

So far so good.

When I repeat this step by creating a second object/model and call ko.applyBindings() I encounter two problems:

  1. The markup shows the previous object/model as well as the new object/model.
  2. A javascript error occurs relating to one of the properties in the object/model, although it's still rendered in the markup.

To get around this problem, after the first pass I call jQuery's .empty() to remove the templated HTML which contains all the data-bind attributes, so that it's no longer in the DOM. When the user starts the process for the second pass the data-bound HTML is re-added to the DOM.

But like I said, when the HTML is re-added to the DOM and re-bound to the new object/model, it still includes data from the the first object/model, and I still get the JS error which doesn't occur during the first pass.

The conclusion appears to be that Knockout is holding on to these bound properties, even though the markup is removed from the DOM.

So what I'm looking for is a means of removing these bound properties from Knockout; telling knockout that there is no longer an observable model. Is there a way to do this?

EDIT

The basic process is that the user uploads a file; the server then responds with a JSON object, the data-bound HTML is added to the DOM, then the JSON object model is bound to this HTML using

mn.AccountCreationModel = new AccountViewModel(jsonData.Account);
ko.applyBindings(mn.AccountCreationModel);

Once the user has made some selections on the model, the same object is posted back to the server, the data-bound HTML is removed from then DOM, and I then have the following JS

mn.AccountCreationModel = null;

When the user wishes to do this once more, all these steps are repeated.

I'm afraid the code is too 'involved' to do a jsFiddle demo.


Source: (StackOverflow)

Advertisements

Why does knockout.js have a reputation for being better for small projects, backbone.js for big?

I've been using knockout.js for a few months, and find it a daily joy to use. The gains from not having to manage state on the dom or apply your own custom bindings is incredible, and I don't mind not having out of the box model features. But every time I read an over-view of knockout.js vs other frameworks the consensus seems to be that it's great, it results in less code and complexity overall, but it's better suited for smaller projects. This statement is always given as a matter of fact, without much explanation so I'm confused as to what the consensus seems to be. (In fairness I have not used Backbone yet and so don't truly know how they compare)

I've used it on two quite large projects, each with about a dozen models and a dozen view-models or so, and have not seen a problem with it. The only downside I can see vs Backbone in a large project is that you are going to get some non-negligible performance hit for having knockout apply and manage all of the bindings. But is that the main concern or is there something else I'm missing?


Source: (StackOverflow)

What is the origin and purpose of the variable $data in KnockoutJS?

In the KnockoutJS tutorials I stumbled upon the following code example that contains an unexplainable variable $data.

The View (html):

<!-- Folders -->
<ul class="folders" data-bind="template: { name: 'folderTemplate', foreach: folders }"></ul>
<script type="text/html" id="folderTemplate">
    <li data-bind="css: { selected: $data == mailViewModel.selectedFolder() },
                   click: function() { mailViewModel.selectFolder($data) }">
        ${$data}
    </li>    
</script>

The View Model (JavaScript):

var viewModel = {
    // Data
    folders: ['Inbox', 'Archive', 'Sent', 'Spam'],
    selectedFolder: ko.observable('Inbox'),

    // Behaviours
    selectFolder: function (folder) {
        this.selectedFolder(folder);
    }    
};

window.mailViewModel = viewModel;
ko.applyBindings(viewModel);

The tutorial does not contain any explanation what that dollar sign is used for and where this $data comes from. The variable $data is nowhere defined and when I rename all three instances of $data to $foobar, the example does not work anymore.

What kind of magic is going on here?


Source: (StackOverflow)

Knockout.js incredibly slow under semi-large datasets

I'm just getting started with Knockout.js (always wanted to try it out, but now I finally have an excuse!) - However, I'm running into some really bad performance problems when binding a table to a relatively small set of data (around 400 rows or so).

In my model, I have the following code:

this.projects = ko.observableArray( [] ); //Bind to empty array at startup

this.loadData = function (data) //Called when AJAX method returns
{
   for(var i = 0; i < data.length; i++)
   {
      this.projects.push(new ResultRow(data[i])); //<-- Bottleneck!
   }
};

The issue is the for loop above takes about 30 seconds or so with around 400 rows. However, if I change the code to:

this.loadData = function (data)
{
   var testArray = []; //<-- Plain ol' Javascript array
   for(var i = 0; i < data.length; i++)
   {
      testArray.push(new ResultRow(data[i]));
   }
};

Then the for loop completes in the blink of an eye. In other words, the push method of Knockout's observableArray object is incredibly slow.

Here is my template:

<tbody data-bind="foreach: projects">
    <tr>
       <td data-bind="text: code"></td>
       <td><a data-bind="projlink: key, text: projname"></td>
       <td data-bind="text: request"></td>
       <td data-bind="text: stage"></td>
       <td data-bind="text: type"></td>
       <td data-bind="text: launch"></td>
       <td><a data-bind="mailto: ownerEmail, text: owner"></a></td>
    </tr>
</tbody>

My Questions:

  1. Is this the right way to bind my data (which comes from an AJAX method) to an observable collection?
  2. I expect push is doing some heavy re-calc every time I call it, such as maybe rebuilding bound DOM objects. Is there a way to either delay this recalc, or perhaps push in all my items at once?

I can add more code if needed, but I'm pretty sure this is what's relevant. For the most part I was just following Knockout tutorials from the site.

UPDATE:

Per the advice below, I've updated my code:

this.loadData = function (data)
{
   var mappedData = $.map(data, function (item) { return new ResultRow(item) });
   this.projects(mappedData);
};

However, this.projects() still takes about 10 seconds for 400 rows. I do admit I'm not sure how fast this would be without Knockout (just adding rows through the DOM), but I have a feeling it would be much faster than 10 seconds.

UPDATE 2:

Per other advice below, I gave jQuery.tmpl a shot (which is natively supported by KnockOut), and this templating engine will draw around 400 rows in just over 3 seconds. This seems like the best approach, short of a solution that would dynamically load in more data as you scroll.


Source: (StackOverflow)

Angular.js and ASP.NET MVC 4 [closed]

I have an ASP.NET MVC 4 project and I'm stuck on an architectural decision on which JavaScript framework or library to use Angular.js or Knock.js. I am currently leaning towards using Angular.js over Knockout.js, but don't want to find out midway during project development I made a mistake.

Here is some background:

  • We need two-way model data binding
  • We need the ability to test views. I want to be able to do end to end unit testing. Also, we are using continuous integration.
  • "Save Changes" functionality. i.e. if a user makes changes on a page we need the ability to detect any changes and prompt the user to save their changes before they navigate away from the page
  • "Notifications" functionality. i.e. user will be logged on approximately 8 hours and will need to be notified and updated of changes made by other users (errors, data status changes and the like)
  • We need to "future proof" our application. Currently the business unit hasn't decided if we will need to support mobile devices, but I know it's just a matter of time.
  • Our team consists of developers with varying experience levels from very junior to senior developers.
  • Currently our models are complicated and may get even more so
  • We need to also consider RAD, code reuse, and maintainability

I have read the excellent answer here and watched Scott Allen's interview about Angular here

Since we are unable to change from our current ASP.NET MVC 4 architecture to use something on the server side like Web API I have some concerns in trying to implement Angular.js with MVC 4. Will this cause us to have two models one on the server and one on the client?

I am not looking for a "which is better" discussion about Angular and Knockout because I think they both have their pros and cons. I am looking for actual code on implementing a JavaScript framework or library in an ASP.NET MVC 4 application. I need a solution that I can live with 2+ years from now :)

Any ideas or suggestions? Maybe the answer is not Knock or Angular, but some other JavaScript framework?


Source: (StackOverflow)

Getting "Cannot read property 'nodeType' of null" when calling ko.applyBindings

I have this knockout code:

function Task(data) {
    this.title = ko.observable(data.title);
    this.isDone = ko.observable(data.isDone);
}

function TaskListViewModel() {
    // Data
    var self = this;
    self.tasks = ko.observableArray([]);
    self.newTaskText = ko.observable();
    self.incompleteTasks = ko.computed(function() {
        return ko.utils.arrayFilter(self.tasks(), function(task) { return !task.isDone() });
    });

    // Operations
    self.addTask = function() {
        self.tasks.push(new Task({ title: this.newTaskText() }));
        self.newTaskText("");
    };
    self.removeTask = function(task) { self.tasks.remove(task) };
}

ko.applyBindings(new TaskListViewModel());

This html:

<head>
    <script type="text/javascript" src="jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="knockout-2.0.0.js"></script>
    <script type="text/javascript" src="script.js"></script>
</head>
<body>
    <h3>Tasks</h3>

    <form data-bind="submit: addTask">
        Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" />
        <button type="submit">Add</button>
    </form>

    <ul data-bind="foreach: tasks, visible: tasks().length > 0">
        <li>
            <input type="checkbox" data-bind="checked: isDone" />
            <input data-bind="value: title, disable: isDone" />
            <a rel='nofollow' href="#" data-bind="click: $parent.removeTask">Delete</a>
        </li> 
    </ul>

    You have <b data-bind="text: incompleteTasks().length">&nbsp;</b> incomplete task(s)
    <span data-bind="visible: incompleteTasks().length == 0"> - it's beer time!</span>
</body>

The example is the same as the one found on the Knockout website, but when I run it, it returns this message on Chrome Fire Bug:

Uncaught TypeError: Cannot read property 'nodeType' of null

This one is related to the knockout file and to this line of my script:

ko.applyBindings(new TaskListViewModel());

And this error is pointing to this line (1766) on knockout:

var isElement = (nodeVerified.nodeType == 1);

What am I doing wrong?


Source: (StackOverflow)

How to use knockout.js with ASP.NET MVC ViewModels?

Bounty

It's been awhile and I still have a couple outstanding questions. I hope by adding a bounty maybe these questions will get answered.

  1. How do you use html helpers with knockout.js
  2. Why was document ready needed to make it work(see first edit for more information)

  3. How do I do something like this if I am using the knockout mapping with my view models? As I do not have a function due to the mapping.

    function AppViewModel() {
    
        // ... leave firstName, lastName, and fullName unchanged here ...
    
        this.capitalizeLastName = function() {
    
        var currentVal = this.lastName();        // Read the current value
    
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    
    };
    
  4. I want to use plugins for instance I want to be able to rollback observables as if a user cancels a request I want to be able to go back to the last value. From my research this seems to be achieved by people making plugins like editables

    How do I use something like that if I am using mapping? I really don’t want to go to a method where I have in my view manual mapping were I map each MVC viewMode field to a KO model field as I want as little inline javascript as possible and that just seems like double the work and that’s why I like that mapping.

  5. I am concerned that to make this work easy (by using mapping) I will lose a lot of KO power but on the other hand I am concerned that manual mapping will just be a lot of work and will make my views contain too much information and might become in the future harder to maintain(say if I remove a property in the MVC model I have to move it also in the KO viewmodel)


Original Post

I am using asp.net mvc 3 and I looking into knockout as it looks pretty cool but I am having a hard time figuring out how it works with asp.net mvc especially view models.

For me right now I do something like this

 public class CourseVM
    {
        public int CourseId { get; set; }
        [Required(ErrorMessage = "Course name is required")]
        [StringLength(40, ErrorMessage = "Course name cannot be this long.")]
        public string CourseName{ get; set; }


        public List<StudentVm> StudentViewModels { get; set; }

}

I would have a Vm that has some basic properties like CourseName and it will have some simple validation on top of it. The Vm model might contain other view models in it as well if needed.

I would then pass this Vm to the View were I would use html helpers to help me display it to the user.

@Html.TextBoxFor(x => x.CourseName)

I might have some foreach loops or something to get the data out of the collection of Student View Models.

Then when I would submit the form I would use jquery and serialize array and send it to a controller action method that would bind it back to the viewmodel.

With knockout.js it is all different as you now got viewmodels for it and from all the examples I seen they don't use html helpers.

How do you use these 2 features of MVC with knockout.js?

I found this video and it briefly(last few minutes of the video @ 18:48) goes into a way to use viewmodels by basically having an inline script that has the knockout.js viewmodel that gets assigned the values in the ViewModel.

Is this the only way to do it? How about in my example with having a collection of viewmodels in it? Do I have to have a foreach loop or something to extract all the values out and assign it into knockout?

As for html helpers the video says nothing about them.

These are the 2 areas that confuses the heck out of me as not many people seem to talk about it and it leaves me confused of how the initial values and everything is getting to the view when ever example is just some hard-coded value example.


Edit

I am trying what Darin Dimitrov has suggested and this seems to work(I had to make some changes to his code though). Not sure why I had to use document ready but somehow everything was not ready without it.

@model MvcApplication1.Models.Test

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
    <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
   <script type="text/javascript">

   $(function()
   {
      var model = @Html.Raw(Json.Encode(Model));


// Activates knockout.js
ko.applyBindings(model);
   });

</script>

</head>
<body>
    <div>
        <p>First name: <strong data-bind="text: FirstName"></strong></p>
        <p>Last name: <strong data-bind="text: LastName"></strong></p>
        @Model.FirstName , @Model.LastName
    </div>
</body>
</html>

I had to wrap it around a jquery document ready to make it work.

I also get this warning. Not sure what it is all about.

Warning 1   Conditional compilation is turned off   -> @Html.Raw

So I have a starting point I guess at least will update when I done some more playing around and how this works.

I am trying to go through the interactive tutorials but use the a ViewModel instead.

Not sure how to tackle these parts yet

function AppViewModel() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");
}

or

function AppViewModel() {
    // ... leave firstName, lastName, and fullName unchanged here ...

    this.capitalizeLastName = function() {
        var currentVal = this.lastName();        // Read the current value
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    };


Edit 2

I been able to figure out the first problem. No clue about the second problem. Yet though. Anyone got any ideas?

 @model MvcApplication1.Models.Test

    @{
        Layout = null;
    }

    <!DOCTYPE html>

    <html>
    <head>
        <title>Index</title>
        <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
       <script type="text/javascript">

       $(function()
       {
        var model = @Html.Raw(Json.Encode(Model));
        var viewModel = ko.mapping.fromJS(model);
        ko.applyBindings(viewModel);

       });

    </script>

    </head>
    <body>
        <div>
            @*grab values from the view model directly*@
            <p>First name: <strong data-bind="text: FirstName"></strong></p>
            <p>Last name: <strong data-bind="text: LastName"></strong></p>

            @*grab values from my second view model that I made*@
            <p>SomeOtherValue <strong data-bind="text: Test2.SomeOtherValue"></strong></p>
            <p>Another <strong data-bind="text: Test2.Another"></strong></p>

            @*allow changes to all the values that should be then sync the above values.*@
            <p>First name: <input data-bind="value: FirstName" /></p>
            <p>Last name: <input data-bind="value: LastName" /></p>
            <p>SomeOtherValue <input data-bind="value: Test2.SomeOtherValue" /></p>
            <p>Another <input data-bind="value: Test2.Another" /></p>

           @* seeing if I can do it with p tags and see if they all update.*@
            <p data-bind="foreach: Test3">
                <strong data-bind="text: Test3Value"></strong> 
            </p>

     @*took my 3rd view model that is in a collection and output all values as a textbox*@       
    <table>
        <thead><tr>
            <th>Test3</th>
        </tr></thead>
          <tbody data-bind="foreach: Test3">
            <tr>
                <td>    
                    <strong data-bind="text: Test3Value"></strong> 
<input type="text" data-bind="value: Test3Value"/>
                </td>
            </tr>    
        </tbody>
    </table>

Controller

  public ActionResult Index()
    {
              Test2 test2 = new Test2
        {
            Another = "test",
            SomeOtherValue = "test2"
        };

        Test vm = new Test
        {
            FirstName = "Bob",
            LastName = "N/A",
             Test2 = test2,

        };
        for (int i = 0; i < 10; i++)
        {
            Test3 test3 = new Test3
            {
                Test3Value = i.ToString()
            };

             vm.Test3.Add(test3);
        }

        return View(vm);
    }

Source: (StackOverflow)

How to force a view refresh without having it trigger automatically from an observable?

Note: this is mostly for debugging and understanding KnockoutJS.

Is there a way to explicitly request Knockout to refresh the view from (already bound) view model? I am looking for something like:

ko.refreshView();

I understand that this is not an intended use of Knockout, but I still want to know if there is a such method for debugging and learning purposes.


Source: (StackOverflow)

How to template If-Else structures in data-bound views?

I constantly find myself using this idiom in KO-based HTML templates:

<!-- ko if: isEdit -->
<td><input type="text" name="email" data-bind="value: email" /></td>
<!-- /ko -->
<!-- ko ifnot: isEdit -->
<td data-bind="text: email"></td>
<!-- /ko -->

Is there a better/cleaner way to do conditionals in KO, or is there a better approach than just using traditional if-else constructs?

Also, I would just like to point out that some versions of Internet Explorer (IE 8/9) don't parse the above example correctly. Please see this SO question for more information. The quick summary is, don't use comments (virtual bindings) inside table tags to support IE. Use the tbody instead:

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>

Source: (StackOverflow)

twitter bootstrap autocomplete dropdown / combobox with Knockoutjs

I have a requirement where I HAVE TO use bootstrap autocomplete dropdown, BUT user can have free form text in that dropdown if they wish. Before you think about TypeAhead, I could use Bootstrap TypeAhead textbox, but I need to have the dropdown becasue we want to give some default values as headstart options in case users dont know what to search for.

I am using this with MVC DropDownListFor as that creates a select control for us.

I found this article which does that for me.

https://github.com/danielfarrell/bootstrap-combobox/pull/20

All I had to do was take off the name from the select control and the control was letting me enter free form text. All good so far.

Now, I am using this in conjunction with Knockoutjs. I bind my options and selected value to the select control and then on row rendered of my template, I called (selector).combobox() which makes the select control a bootstrap comobobox and adds an input control and hides the select control in the scenes behind.

The problem now is when I try to get he values to post to server, since the value I put in input box is not a valid options from the options I gave to select control, it is always setting it to the first option by default. This is becasue, I set the binding of the selected value on select control and not on the input box which was created by bootstrap-combobox.js.

My question is how do I get the input box to data-bind to the same porperty as the the select control was bound to.

Any other options?? Let me know if you need more clarification or have questions. Please suggest.

Thanks.


Source: (StackOverflow)

Binding true / false to radio buttons in Knockout JS

In my view model I have a IsMale value that has the value true or false.

In my UI I wish to bind it to the following radio buttons:

<label>Male
   <input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/>
</label> 
<label>Female
   <input type="radio" name="IsMale" value="false" data-bind="checked:IsMale"/>
</label>

The problem I think is checked expects a string "true" / "false". So my question is, how can I get this 2-way binding w/ this UI and model?


Source: (StackOverflow)

When to use ko.utils.unwrapObservable?

I've written a few custom bindings using KnockoutJS. I'm still unsure when to use ko.util.unwrapObservable(item) Looking at the code, that call basically checks to see if item is an observable. If it is, return the value(), if it's not, just return the value. Looking at the section on Knockout about creating custom bindings, they have the following syntax:

var value = valueAccessor(), allBindings = allBindingsAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);

In this case, they invoke the observable via () but then also call ko.utils.unwrapObservable. I'm just trying to get a handle on when to use one vs. the other or if I should just always follow the above pattern and use both.


Source: (StackOverflow)

How to architecture a webapp using jquery-mobile and knockoutjs

I would like to build a mobile app, brewed from nothing more but html/css and JavaScript. While I have a decent knowledge of how to build a web app with JavaScript, I thought I might have a look into a framework like jquery-mobile.

At first, I thought jquery-mobile was nothing more then a widget framework which targets mobile browsers. Very similar to jquery-ui but for the mobile world. But I noticed that jquery-mobile is more than that. It comes with a bunch of architecture and let's you create apps with a declarative html syntax. So for the most easy thinkable app, you wouldn't need to write a single line of JavaScript by yourself (which is cool, because we all like to work less, don't we?)

To support the approach of creating apps using a declarative html syntax, I think it's a good take to combine jquery-mobile with knockoutjs. Knockoutjs is a client-side MVVM framework that aims to bring MVVM super powers known from WPF/Silverlight to the JavaScript world.

For me MVVM is a new world. While I have already read a lot about it, I have never actually used it myself before.

So this posting is about how to architecture an app using jquery-mobile and knockoutjs together. My idea was to write down the approach that I came up with after looking at it for several hours, and have some jquery-mobile/knockout yoda to comment it, showing me why it sucks and why I shouldn't do programming in the first place ;-)

The html

jquery-mobile does a good job providing a basic structure model of pages. While I am well aware that I could have my pages to be loaded via ajax afterwards, I just decided to keep all of them in one index.html file. In this basic scenario we are talking about two pages so that it shouldn't be too hard to stay on top of things.

<!DOCTYPE html> 
<html> 
  <head> 
  <title>Page Title</title> 
  <link rel="stylesheet" rel='nofollow' href="libs/jquery-mobile/jquery.mobile-1.0a4.1.css" />
  <link rel="stylesheet" rel='nofollow' href="app/base/css/base.css" />
  <script src="libs/jquery/jquery-1.5.0.min.js"></script>
  <script src="libs/knockout/knockout-1.2.0.js"></script>
  <script src="libs/knockout/knockout-bindings-jqm.js" type="text/javascript"></script>
  <script src="libs/rx/rx.js" type="text/javascript"></script>
  <script src="app/App.js"></script>
  <script src="app/App.ViewModels.HomeScreenViewModel.js"></script>
  <script src="app/App.MockedStatisticsService.js"></script>
  <script src="libs/jquery-mobile/jquery.mobile-1.0a4.1.js"></script>  
</head> 
<body> 

<!-- Start of first page -->
<div data-role="page" id="home">

    <div data-role="header">
        <h1>Demo App</h1>
    </div><!-- /header -->

    <div data-role="content">   

    <div class="ui-grid-a">
        <div class="ui-block-a">
            <div class="ui-bar" style="height:120px">
                <h1>Tours today (please wait 10 seconds to see the effect)</h1>
                <p><span data-bind="text: toursTotal"></span> total</p>
                <p><span data-bind="text: toursRunning"></span> running</p>
                <p><span data-bind="text: toursCompleted"></span> completed</p>     
            </div>
        </div>
    </div>

    <fieldset class="ui-grid-a">
        <div class="ui-block-a"><button data-bind="click: showTourList, jqmButtonEnabled: toursAvailable" data-theme="a">Tour List</button></div>  
    </fieldset>

    </div><!-- /content -->

    <div data-role="footer" data-position="fixed">
        <h4>by Christoph Burgdorf</h4>
    </div><!-- /header -->
</div><!-- /page -->

<!-- tourlist page -->
<div data-role="page" id="tourlist">

    <div data-role="header">
        <h1>Bar</h1>
    </div><!-- /header -->

    <div data-role="content">   
        <p><a rel='nofollow' href="#home">Back to home</a></p> 
    </div><!-- /content -->

    <div data-role="footer" data-position="fixed">
        <h4>by Christoph Burgdorf</h4>
    </div><!-- /header -->
</div><!-- /page -->

</body>
</html>

The JavaScript

So let's come to the fun part - the JavaScript!

When I started to think about layering the app, I have had several things in mind (e.g. testability, loose coupling). I'm going to show you how I decided to split of my files and comment things like why did I choose one thing over another while I go...

App.js

var App = window.App = {};
App.ViewModels = {};

$(document).bind('mobileinit', function(){
    // while app is running use App.Service.mockStatistic({ToursCompleted: 45}); to fake backend data from the console
    var service = App.Service = new App.MockedStatisticService();    

  $('#home').live('pagecreate', function(event, ui){
        var viewModel = new App.ViewModels.HomeScreenViewModel(service);
        ko.applyBindings(viewModel, this);
        viewModel.startServicePolling();
  });
});

App.js is the entry point of my app. It creates the App object and provides a namespace for the view models (soon to come). It listenes for the mobileinit event which jquery-mobile provides.

As you can see, I'm creating a instance of some kind of ajax service (which we will look at later) and save it to the variable "service".

I also hook up the pagecreate event for the home page in which I create an instance of the viewModel that gets the service instance passed in. This point is essential to me. If anybody thinks, this should be done differently, please share your thoughts!

The point is, the view model needs to operate on a service (GetTour/, SaveTour etc.). But I don't want the ViewModel to know any more about it. So for example, in our case, I'm just passing in a mocked ajax service because the backend hasn't been developed yet.

Another thing I should mention is that the ViewModel has zero knowledge about the actual view. That's why I'm calling ko.applyBindings(viewModel, this) from within the pagecreate handler. I wanted to keep the view model seperated from the actual view to make it easier to test it.

App.ViewModels.HomeScreenViewModel.js

(function(App){
  App.ViewModels.HomeScreenViewModel = function(service){
    var self = {}, disposableServicePoller = Rx.Disposable.Empty;

    self.toursTotal = ko.observable(0);
    self.toursRunning = ko.observable(0);
    self.toursCompleted = ko.observable(0);
    self.toursAvailable = ko.dependentObservable(function(){ return this.toursTotal() > 0; }, self);
    self.showTourList = function(){ $.mobile.changePage('#tourlist', 'pop', false, true); };        
    self.startServicePolling = function(){  
        disposableServicePoller = Rx.Observable
            .Interval(10000)
            .Select(service.getStatistics)
            .Switch()
            .Subscribe(function(statistics){
                self.toursTotal(statistics.ToursTotal);
                self.toursRunning(statistics.ToursRunning); 
                self.toursCompleted(statistics.ToursCompleted); 
            });
    };
    self.stopServicePolling = disposableServicePoller.Dispose;      

    return self; 
  };
})(App)

While you will find most knockoutjs view model examples using an object literal syntax, I'm using the traditional function syntax with a 'self' helper objects. Basically, it's a matter of taste. But when you want to have one observable property to reference another, you can't write down the object literal in one go which makes it less symmetric. That's one of the reason why I'm choosing a different syntax.

The next reason is the service that I can pass on as a parameter as I mentioned before.

There is one more thing with this view model which I'm not sure if I did choose the right way. I want to poll the ajax service periodically to fetch the results from the server. So, I have choosen to implement startServicePolling/*stopServicePolling* methods to do so. The idea is to start the polling on pageshow, and stop it when the user navigates to different page.

You can ignore the syntax which is used to poll the service. It's RxJS magic. Just be sure I'm polling it and update the observable properties with the returned result as you can see in the Subscribe(function(statistics){..}) part.

App.MockedStatisticsService.js

Ok, there is just one thing left to show you. It's the actual service implementation. I'm not going much into detail here. It's just a mock that returns some numbers when getStatistics is called. There is another method mockStatistics which I use to set new values through the browsers js console while the app is running.

(function(App){
    App.MockedStatisticService = function(){
        var self = {},
        defaultStatistic = {
            ToursTotal: 505,
            ToursRunning: 110,
            ToursCompleted: 115 
        },
        currentStatistic = $.extend({}, defaultStatistic);;

        self.mockStatistic = function(statistics){
            currentStatistic = $.extend({}, defaultStatistic, statistics);
        };

        self.getStatistics = function(){        
            var asyncSubject = new Rx.AsyncSubject();
            asyncSubject.OnNext(currentStatistic);
            asyncSubject.OnCompleted();
            return asyncSubject.AsObservable();
        };

        return self;
    };
})(App)

Ok, I wrote much more as I initially planned to write. My finger hurt, my dogs are asking me to take them for a walk and I feel exhausted. I'm sure there are plenty things missing here and that I put in a bunch of typos and grammer mistakes. Yell at me if something isn't clear and I will update the posting later.

The posting might not seem as an question but actually it is! I would like you to share your thoughts about my approach and if you think it's good or bad or if I'm missing out things.

UPDATE

Due to the major popularity this posting gained and because several people asked me to do so, I have put the code of this example on github:

https://github.com/cburgdorf/stackoverflow-knockout-example

Get it while it's hot!


Source: (StackOverflow)

How to conditionally push an item in an observable array?

I would like to push a new item onto an observableArray, but only if the item is not already present. Is there any "find" function or recommended pattern for achieving this in KnockoutJS?

I've noticed that the remove function on an observableArray can receive a function for passing in a condition. I almost want the same functionality, but to only push it if the condition passed in is or is not true.


Source: (StackOverflow)