Click here to Skip to main content
Click here to Skip to main content

Knockout js for Beginners

, 12 Nov 2013
Rate this:
Please Sign up or sign in to vote.
This article will help begenners to understand how knock out will work with asp.net and communicate client-side server side and the usefulness of the responsive ui design.

Introduction 

Knockout js (shortly called KO) is a very popular JavaScript library and increasing its popularity day by day. This library helps to create rich/responsive/interactive web applications. It works directly with the web application's underlying data model. Using KO with any web application is very simple, clean, and straightforward, it is very powerful in the context of dynamic UI creation.  

Background 

JavaScript plays a very important role for developing today's modern web applications. Once upon a time, we just wrote a few JavaScript lines for data validation from the client side. But day by day JavaScript plays a vital role not only in data validation but also for creating responsive, robust web UI. For that reason, day by day a new JavaScript framework/library comes into market. We as smart developers, must adopt them and try to use them with our applications.  

Benefits   

If we use KO with web applications, we can get following benefits 

  • Anytime we can connect UI elements with data model. 
  • Easily create complex dynamic data model.  
  • Automatically update UI when Data Model is changed, when UI is changed then Data Model is changed automatically.  
  • Support event-driven programming model.  
  • Extend custom behavior very easily. 
  • All main-stream browsers are supported (IE, FireFox, Crome, Safari)   

KO with MVVM   

What is MVVM? Well, The full form of MVVM is Model View ViewModel. It is an architectural design pattern origined by Microsoft and mainly created for WPF/Silverlight applications. But we can use this Web application too with ASP.NET.   

MVVM is a specific implementation targeted at UI development platform which support event driven programming for WPF/Silverlight. It respect the programming principle "Separation of Concern". It completely separate GUI Rendering logic from Application Logic (Data Logic/Business Logic).   

KO built on that architectural design pattern. So if you want to understand KO properly then you should know about MVVM first.  

MVVM Overview   

The following diagram will show the style of MVVM 

MVVM has 3 parts:

  1. Model 
  2. View    
  3. ViewModel    
  • Model: Responsible for holding Application data. When  User enter data with UI elements, That data will store to a Model. So we can thinks like it is data part of the pattern.
  • View:  Responsible for presenting model data to the user. User elements are the part of the View. It provide structure/Layout of the User Interface and present to the user.
  • ViewModel: Connector of Model and View. Main responsibility is establish communication with View and Model. It hold data and function. Functions manipulate that data and it reflect to the UI. When data changed, UI is changed, when UI changed data is changed. ViewModel will does it for us with the help of databinding concept. 

MVVM Benefits 

Main benefits of MVVM:

  • Provide more flexibility  of designer and developer works.
  • Thorough unit testing 
  • Provide flexibility to change user interface without having to re-factor other logic of the codebase.
  • Provide more re-usability of UI component.   

Include KO library to Web Application 

CDN (Content Delivery Network) reference of Knockout js is available at Microsoft CDN repository. There are two versions available. One for compact (minified) another for debug. It is recommended to use minified version. The url are

If your application is ASP.NET WebForm then you can download js file from above locations and store it to your web folder/subfolder and reference it to your page/master page.

<script src="~/Scripts/knockout-2.2.1.js" type="text/javascript"></script>
CDN Reference:
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js" type="text/javascript"></script>  

 If ASP.NET MVC application you can take reference inside @section  

@section scripts {
    <script src="~/Scripts/knockout-2.2.1.js"></script>
}
CDN Reference: 
@section scripts {
    <script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js"></script>
} 

Example-1 

I will create a simple Employee information entry form. Form will accept some basic employee related data from the user and submit that data to the MVC Action with the help of AJAX. In View part , I will use various html element so that I can show how all elements are worked with KO. 

Implementation: 

Before start showing  code with KO just mention one thing. In MVVM pattern, a personal choice is there. That is which come first, Model Or View. I am not going to discuss detail on that. Just mention my personal preference and that is View. I always like to start View first then for Model. 

<form id="employeeForm" name="employeeForm" method="POST">
    <div id="form-root">
        <div>
            <label class="form-label">First Name:</label>
            <input type="text" id="txtFirstName" 
              name="txtFirstName" data-bind="value:Employee.FirstName" />
        </div>
         <div>
            <label class="form-label">Last Name:</label>
            <input type="text" id="txtLastName" 
              name="txtLastName" data-bind="value:Employee.LastName"  />
        </div>
        <div>
            <label class="form-label">Full Name:</label>
            <input type="text" id="txtFullName" name="txtFullName" 
              data-bind="value:Employee.FullName" readonly="readonly"  />
        </div>
        <div>
            <label class="form-label">Date Of Birth:</label>
            <input type="text" id="txtDateOfBirth" 
              name="dateOfBirth" data-bind="value:Employee.DateOfBirth"  />
        </div>
        <div>
            <label>Education:</label>
            <input type="checkbox" value="graduation" id="chkGraduation" 
              name="chkGraduation" data-bind="checked:Employee.EducationList" />Graduation
            <input type="checkbox" value="postGraduation" 
              id="chkPostGraduation" name="chkPostGraduation" 
              data-bind="checked:Employee.EducationList" />PostGraduation
        </div>
        <div>
            <label>Gender:</label>
            <input type="radio" id="rdoMale" name="gender" 
              value="0"  data-bind="checked:Employee.Gender" />Male
            <input type="radio" id="rdoFeMale" name="gender" 
              value="1" data-bind="checked:Employee.Gender"  />FeMale
        </div>
        <div>
            <label class="form-label">Department:</label>
            <select id="ddlDepartment" name="ddlDepartment" 
              data-bind="options:$root.Employee.DepartmentList, optionsValue:'Id', 
                optionsText:'Name', value:Employee.DepartmentId">
            </select>
        </div>
        <div>
            <input type="button" id="btnSubmit" 
              value="Submit" data-bind = "click: submit" />
             <input type="button" id="btnReset" 
               value="Reset" data-bind = "click: reset" />
        </div>
    </div>
</form>

View: 

First I create a view.Its looks like:

 

I bind all of view's html form element with my client side model with KO's data-bind attribute.  Why i said Client Side Model? Because i have a Server Side Model too. Letter I talk about server side model. With Data-Bind attribute, KO connect UI element to the Model property. Now explain UI elements connect to the Data Memeber of the Model one by one.

TextBox Binding: 

<input type="text" id="txtFirstName" name="txtFirstName" data-bind="value:Employee.FirstName" /> 

Html form element textbox bind with FirstName property of Employee Model. value is the KO key by which KO address textbox value property. But remember that value inside data-bind attribute is the KO's key not html native. When textbox value is updated then FirstName property of the Employee model will be updated automatically and vice-versa. No custom code is needed for that.

CheckBox Binding: 

<input type="checkbox" value="graduation" 
  id="chkGraduation" name="chkGraduation" data-bind="checked:Employee.EducationList" />
<input type="checkbox" value="postGraduation" id="chkPostGraduation" 
  name="chkPostGraduation" data-bind="checked:Employee.EducationList" /> 

HTML form element checkbox (input checkbox) is bind with EducationList string array of Employee Model. Here both checkbox is bind with single model property. When user checked any/both checkbox, automatically the value of the checkboxes (1st checkbox value is "graduation" 2nd is "PostGraduation")  will be added to the array. If un-checked then the value will be removed from this array. In textbox we use KO's key value, in checkbox here we use another KO's key named checked.  Again checked in not any HTML native.  

Radio-Button Binding: 

<input type="radio" id="rdoMale" name="gender" 
   value="0"  data-bind="checked:Employee.Gender" />
<input type="radio" id="rdoFeMale" name="gender" 
  value="1" data-bind="checked:Employee.Gender"  /> 

There are two radio buttons and grouped it with name property. If radio-buttons name is same then they work like group. If one radio is selected then automatically others will be de-selected and vice-versa. Both radio buttons are bind with single Employee Model property named Gender (number type). When Male will select then this property will contain 0, if FeMale select, it will contain 1. Same way when Gender contain 0 then rdoMale radio will be selected, when Gender contain 1 then rdoFemale will be selected (checked). 

Drop-Down/ComboBox/Select Binding: 

<select id="ddlDepartment" name="ddlDepartment" 
    data-bind="options:$root.Employee.DepartmentList, optionsValue:'Id', 
      optionsText:'Name', value:Employee.DepartmentId">
</select>  

Drop-down list is bind with two Model properties. For its data source, it binds DepartmentList array of object of Employee Model. Object has 2 properties. Id and Name. Id Bind with value and Name bind with option text. Means, drop-down will show all Name of the objects. Drop-down selected value is bind with DepartmentId property. When user select any item from drop-down, the value of the item will store in DepartmentId. Sameway if any value assign to the DepartmentId from the ViewModel then drop-down will show that item which match the value to the user.

Button/Command Button Binding: 

<input type="button" id="btnSubmit" value="Submit" data-bind = "click: submit" />  

Button is bind with submit method of the ViewModel with click event. When user click Submit button then submit method of the ViewModel  will fire. 

There are so many keywords are used in data-binding in KO. All are KO's own keyword. It should be clear that those are not HTML native property. 

Model:

function Employee() {
    var that = this;
    that.FirstName = ko.observable("");
    that.LastName = ko.observable("");
    that.FullName = ko.computed(function () {
        return that.FirstName() + " " + that.LastName();
    });
    that.DateOfBirth = ko.observable("");
    that.EducationList = ko.observableArray();
    that.Gender = ko.observable("0");
    that.DepartmentList = ko.observableArray([{ Id: '0', Name: "CSE" }, { Id: '1', Name: "MBA" }]);
    that.DepartmentId = ko.observable("1");
} 

Employee is my Model. We can call it data model. In its every property i initialize with ko.observable method. What does the actual ko.observable method return? It returns a function, which notify ui element for update. So in property of Employee like FirstName, LastName etc all are functions. If I want to assign any value to the FirstName then code should be that.FirstName("Mr."), if read that property then it should be that.FirstName() computed is another ko library function which is responsible for dependency tracking. Means, inside that function i use FirstName and LastName property. When FirstName or LastName property is updated then fullName is automatically updated. 

KO has another important things that is Observable Array. It is nothing but a collection of observable method. Each and every item of array will be observable. If i want to add value to that array then i need to use

that.DepartmentList.push({Id:3, Name:"BBA"}); 

If want to remove last item of the array the

that.DepartmentList.pop(); 

It might be confused that push and pop are the javascript array native method. But here use push and pop with observable array are not the native javascript method. It is actually KO's own implemented method. KO implements 6 methods for observable array.

  1. push
  2. pup
  3. unshift
  4. shift
  5. reverse
  6. sort 

So be clear on that and not to confuse javascript array object's method with that. 

ViewModel:

function EmployeeVM() {
    var that = this;
    that.Employee = new Employee();
    that.reset = function () {
        that.Employee.FirstName("");
        that.Employee.LastName("");
        that.Employee.DateOfBirth("");
    };
    that.submit = function () {
        var json1 = ko.toJSON(that.Employee);
        $.ajax({
            url: '/Employee/SaveEmployee',
            type: 'POST',
            dataType: 'json',
            data: json1,
            contentType: 'application/json; charset=utf-8',
            success: function (data) {
                var message = data.Message;
            }
        });
    };
}; 

that.Employee is hold the reference of Employee Model. Here i implement 2 behaviors 

  1. reset: reset method will re-initialize the value of the model.   
  2. submit: convert Employee model data to jason string and send it to the server's SaveEmployee action method with the help of JQuery ajax method.    

Controller Action:

[HttpPost]
public  ActionResult SaveEmployee(Employee emp)
{
    //EmployeeModel save code here
    return View("EmployeeInfo");
} 

This is the Employee controller action method. submit method of client side view model send data to this action method. Actually this action receives data from client view and process that data then save that data to the database or throw exception if any invalid things happen.

 

Server side Model:

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public Gender Gender { get; set; }
    public IList<string> EducationList { get; set; }
    public int DepartmentId { get; set; }
}
public enum Gender
{
    Male =0,
    FeMale = 1
} 

This is my server side Employee Model. Why server side Model is required? We see that from my client part we create an Employee ViewModel. But it should be in mind that in client side we actually do not write any business logic. My application process business logic. Then where i write that? For server side business logic handle, we create server side Model and we send that model to various layers like domain service layer/Repository layer etc.  

Example-2 

I will create an Employee phone entry form. Employee could have multiple phone number with country code. First time view will show to add a single phone number entry option. If user wants than if he press Add button then it will create another phone number entry option dynamically to the user interface. User can also remove any phone number entry option with press Remove button. So we understand that there dynamic ui rendering feature will come. Lets see how knockout will help in this area.

Implementation: 

View:

First i will complete view creation part. View looks 

 

<form id="employeeForm" name="employeeForm" method="POST">
    <script id="PhoneTemplate" type="text/html">
        <div>
            <span>
                <label>Country Code:</label>
                <input type="text" id="txtCountryCode" data-bind="value:CountryCode" />
            </span>
            <span>
                <label>Phone Number:</label>
                <input type="text" id="txtPhoneNumber" data-bind="value:PhoneNumber" />
            </span>
            <input type="button" id="btnRemove" 
              value="Remove" data-bind="click: $parent.remove" />
        </div>
    </script>
    <div>
        <h2>Employee Phone Number</h2>
        <div data-bind="template:{name:'PhoneTemplate', foreach:PhoneList}, visible:isVisible">
        </div>
        <div>
            <input type="button" id="btnAdd" 
              value="Add Another" data-bind="click: add" />
        </div>
    </div>
</form> 

KO supports data template. It develops template engine for rendering template. This is also works with jQuery template too. I create a template named PhoneTemplate. 

<script id="PhoneTemplate" type="text/html"> </script> 

I declare type="text/html"  with script tag. That mean I knotify browser that it is text data and you will not execute it. Inside that script block I create a div. Inside that div i create 2 html textbox, 2 labels and 1 button.

Outside the script block i create another div and bind that div to my javascript viewmodel's array member PhoneList. KO has its own syntax to bind with template. Here inside the data-bind attribute I declare, 

<div data-bind="template:{name:'PhoneTemplate', foreach:PhoneList}">
</div>  

it bind with a template named 'Phonetemplate' and use foreach statement. That  means render this referenced template equal to no of items found in PhoneList.  If i dynamically add item to the PhoneList then template will render with  again with new UI and same way if i remove item from this array automatically ui element which renders when item is added will be removed. 

Model:

function Phone(code, number) {
    var self = this;
    self.CountryCode = ko.observable(code);
    self.PhoneNumber = ko.observable(number);
}  

Client side Javascript Model has 2 properties  

  1. CountryCode  
  2. PhoneNumber   

Each property initialize with observable method so that it can works with KO. This two properties is used inside template. 

ViewModel:

function PhoneViewModel() {
    var self = this;
    self.PhoneList = ko.observableArray([new Phone("00", "00-00-00")]);
    self.remove = function () {
        self.PhoneList.remove(this);
    };
    self.add = function () {
        self.PhoneList.push(new Phone("01", "00-00-01"));
    };
}  

PhoneViewModel establish connection between Phone View and Phone Model with the help of data-bind attribute. This ViewModel contains 2 methods 

  1. add 
  2. remove   

when user press 'Add Another" button, It will create a new Phone Model with default value and add it to the PhoneList array. When PhoneList array is added new item, automatically UI create a new div based on designed template. 

When user press "Remove" button, it will call remove method of ViewModel and remove current item from the PhoneList array. When an item is removed from array then automatically ui is re-populated. 

View & ViewModel Relation

When you start implemting MVVM to your web appliation then one issue might face that is how many ViewModel needed for a view for vise-versa. Means what type of relation needed for view and model/ViewModel.

There are few opinion exists in the market

  •     One-View to One-ViewModel
  •     Many-Views to many-ViewModels
  •     One-View to many-ViewModels

Theare is no hard and fix rule here. Many people including me support Per View will have single ViewModel and per ViewModel will have single Model. It will helps us to keep code simpler and more managable.

If Re-usability concern then I think, You can use many views with a single ViewModel.

Points of Interest 

Knockout js such a library that are using in our web application. So we need to enrich our knowledge to this library so that any of our web project we can use it smoothly.

I also like angular js very much. Many SPA(Single Page Application) use this library too. I will write my next article on that library.  

Source Code  

I upload a sample project with this article. That is MVC project with ASP.NET 4.5 version with Visual Studio 2012. If you are a WebForm developer then just download the code and add it to your WebForm project and little customize for the server side code. Replace a web method instead of ASP.NET Action method and it will work perfectly. Knock-out is not tightly couple with any project template like MVC or WebForm or any other. In all places you can work with it.  

References  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

S. M. Ahasan Habib
Software Developer (Senior) The Jaxara IT Ltd.
Bangladesh Bangladesh
Mostly I work with MS technologies (ASP.NET MVC, WPF, C#, SQL Server, SSRS, SharePoint, Entity Framework, MSTest, Enterprise Library, MEF, WCF, WebAPI, MS Excel, IIS).
Non MS technologies which I love and use (Resharper, NHiberNet, JQuery, AngularJS, KnockoutJS, NodeJS, Python, MSpec, RihnoMock, Crystal Report, Subversion, Crome)

Comments and Discussions

 
QuestionBinding Model Value to View Pinmembera b28-Jul-14 23:25 
QuestionClient side error Pinmembersbrahul27-Jul-14 20:53 
AnswerRe: Client side error Pinmembersbrahul27-Jul-14 21:00 
GeneralMy vote of 5 Pinmemberkentclark51916-Jul-14 8:25 
GeneralMy vote of 5 Pinmembermehedi195014-Jul-14 14:00 
GeneralMy vote of 4 PinprofessionalDebabrata_Das13-Jul-14 7:43 
GeneralMy vote of 2 PinmemberKanupriyaGoel18-Jun-14 21:57 
Questionnice exmplanation PinmemberBorshon Aeolus Saydur5-Jun-14 0:17 
AnswerRe: nice exmplanation PinpremiumS. M. Ahasan Habib5-Jun-14 1:08 
GeneralMy vote of 3 PinmemberMember 1002269623-May-14 4:46 
QuestionGood Explanation PinprofessionalConnectingKamlesh6-May-14 23:40 
AnswerRe: Good Explanation PinpremiumS. M. Ahasan Habib7-May-14 1:05 
QuestionIt saved my day!! Pinmemberdecentajay13-Apr-14 13:38 
AnswerRe: It saved my day!! PinpremiumS. M. Ahasan Habib13-Apr-14 19:18 
QuestionVery Useful PinmemberVipin_Arora21-Mar-14 23:45 
AnswerRe: Very Useful PinpremiumS. M. Ahasan Habib22-Mar-14 20:20 
GeneralRe: Very Useful PinmemberVipin_Arora23-Mar-14 5:43 
GeneralRe: Very Useful PinpremiumS. M. Ahasan Habib23-Mar-14 8:15 
QuestionRe: Very Useful PinmemberVipin_Arora23-Mar-14 17:14 
AnswerRe: Very Useful PinpremiumS. M. Ahasan Habib23-Mar-14 17:28 
Questionapplybinding method PinmemberMember 103179135-Jan-14 18:11 
AnswerRe: applybinding method PinprofessionalS. M. Ahasan Habib5-Jan-14 18:23 
GeneralMy vote of 5 PinprofessionalAmir Hamza Md. Kayes10-Dec-13 8:34 
GeneralRe: My vote of 5 PinprofessionalS. M. Ahasan Habib10-Dec-13 13:31 
GeneralMy vote of 5 PinprofessionalRenju Vinod9-Dec-13 1:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 13 Nov 2013
Article Copyright 2013 by S. M. Ahasan Habib
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid