Dynamic UI in ASP.NET MVC using Knockout.js and Template binding

Recently I was discussing capabilities of the client-side framework Knockout.js in ASP.NET MVC applications, with some of my students. KO is a lightweight framework and very efficient for developing rich Web application.

You can find more about this library here. For a more practical implementation, you can find two articles - Simple Databinding and Templating using Knockout and ASP.NET Web API and Simple Application using Knockout.js, jQuery and ASP.NET MVC 4.0 with WEB API.

One of the most awesome features in KO is ‘template’ binding. This is a simple mechanism for building UI structures with repeating UI blocks. Templates support data binding expressions to bind various HTML attributes (text, value, id, url etc.) to the data in the view model.

Typically, the template binding mechanism is used when the HTML table with rows or unordered or ordered lists need to be generated dynamically based upon the data received from the external source like WEB API or WCF Services.

The knockout.js framework supports two types of templates. First is Native templating, which is based upon the control flows like foreach, with etc. This is built into knockout. The other is String based templating, which is used to connect to third party template engine.


The Sample Knockout ASP.NET MVC App

For demo purposes, the EmployeeInfo table in Company database of SQL Server is used. The script is as below:

Create database Company
USE [Company]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[EmployeeInfo](
    [EmpNo] [int] IDENTITY(1,1) NOT NULL,
    [EmpName] [varchar](50) NOT NULL,
    [Salary] [decimal](18, 0) NOT NULL,
    [DeptName] [varchar](50) NOT NULL,
    [Designation] [varchar](50) NOT NULL,
CONSTRAINT [PK_EmployeeInfo] PRIMARY KEY CLUSTERED
(
    [EmpNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO

Step 1: Open VS 2012 and create a new ASP.NET MVC 4 application, name it as ‘MVC40_DynamicUI_Generation_Using_KnockoutJS’. In this project, add the ADO.NET EF and complete the wizard which will map with the EmployeeInfo table created above.

Step 2: In the controller folder, add a new API controller and name it as EmployeeInfoAPI. This API controller should be based upon the ADO.NET EF added in Step 1.

mvc-api-controller

Step 3: In the controller folder, add a new empty MVC Controller of name EmployeeInfoController as below:

empty-mvc-controller

Step 4: From the Index action method of the above controller, add a new Empty Index view.

Step 5: Add the following script references in the Index.cshtml:

<script src="~/Scripts/jquery-1.9.1.min.js"></script>
<script src="~/Scripts/knockout-2.2.1.js"></script>

Note: By default you will have older versions of jquery and knockout script in your project. It is recommended that you upgrade to use latest versions from NuGet.

Step 6: In the Index.cshtml add below JavaScript:

<script type="text/javascript">
function EmployeeInfoViewModel() {
  var self = this;
  self.Employees = ko.observableArray([]);
  $.ajax({
   type: "GET",
   url: "http://localhost:1452/api/EmployeeInfoAPI",
   contentType: "application/json; charset=utf-8",
   dataType: "json",
   success: function (data) {
    self.Employees(data);
   },
   error: function (error) {
    alert(error.status + "<--and--> " + error.statusText);
   }
  });
}
$(document).ready(function () {
  ko.applyBindings(new EmployeeInfoViewModel());
});
</script>

  
The above script, defines the EmployeeInfoView model. This defines an observableArray of name Employees. This array will store the Employee data received after making an AJAX call to Web API. When the AJAX call is successful, the received data will be stored into the observable array.

Step 7: Use the following HTML:

<table>
<thead>
  <tr>
   <th>EmpNo</th>
   <th>EmpName</th>
   <th>Salary</th>
   <th>DeptName</th>
   <th>Designation</th>
   <th></th>
</tr>
</thead>
<tbody data-bind="template: { name: 'EmpRecord', foreach: Employees }">
</tbody>
</table>

<!---Html Template-->
<script id="EmpRecord" type="text/html">
<tr>
  <td>
   <input type="text" style="width:100px;"  data-bind="value: $data.EmpNo"  disabled="disabled" />
  </td>
  <td>
   <input type="text" style="width:100px;"  data-bind="value: $data.EmpName" />
  </td>
  <td>
   <input type="text" style="width:100px;"  data-bind="value: $data.Salary" />
  </td>
  <td>
   <input type="text" style="width:100px;"  data-bind="value: $data.DeptName"  />
  </td>
  <td>
   <input type="text" style="width:100px;"  data-bind="value:  $data.Designation" />
  </td>
</tr>
</script>
<!---Html Template-->

  
In the above markup, the HTML template with id as ‘EmpRecord’ is defined. This contains input tags which bind with EmployeeInfo properties e.g. EmpNo, EmpName etc using value binding.

The tbody is bound with the template using ‘template’ binding. This contain the following parameters:

name: This is the ‘id’ of the element which contains the template.
foreach: This implies that Knockout should render the template in foreach mode. This means that the template will render for the number of records passed to the foreach binding.

Step 8: Run the application, and navigate to the EmployeeInfo/Index in the url, the result will be as shown below:

dynamic-bound-knockout

Download the entire source code of this article (Github)




About The Author

Mahesh Sabnis is a Microsoft MVP having over 18 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). He also blogs regularly at DotNetCurry.com. Follow him on twitter @maheshdotnet