Please enable Javascript to correctly display the contents on Dot Net Tricks!

Understanding Knockout Binding Context Variable

  Author : Shailendra Chauhan
Updated On : 26 Sep 2016
Total Views : 24,482   
 

Basically, binding context is an object that holds data, which is referenced from your view-model bindings. While applying bindings, Knockout automatically creates and manages a hierarchy of binding contexts. Let's have a look on different types of binding context with example.

The $root Property

The $root context always refers to the top-level ViewModel, regardless of loops or other changes in scope. This allow us to access top-level methods for manipulating the ViewModel.

For example, inside the foreach: shoppingCart loop, $root refers to top-level methods removeProduct of ViewModel as shown below:

<tbody data-bind='foreach: shoppingCart'>
 <tr>
 .
 . 
 <td>
<button data-bind='click: $root.removeProduct'>Remove</button>
</td>
</tr>
</tbody>

The $data Property

The $data binding context refers to the ViewModel object in the current context. It is much more like the this keyword in a JavaScript object.

For example, inside the foreach: shoppingCart loop, $data refers to the current list item as shown below:

<tr data-bind='foreach: shoppingCart'>
<td data-bind='text: $data.name'></td>
<td data-bind='text: $data.price'></td>
</tr>

The $index Property

Inside of a foreach loop, the $index property contains the current item’s index in the array. Unlike the other binding context properties, $index is an observable and is updated automatically whenever you add or delete an item from the associated observable array.

<tr data-bind='foreach: shoppingCart'>
<td data-bind='text: $index'></td>
<td data-bind='text: $data.name'></td>
<td data-bind='text: $data.price'></td>
</tr>

The $parent Property

The $parent property context refers to the parent ViewModel object. Typically, you will require this prroperty when you will work with nested loops and with in the nested loop, you need to access properties of the outer loop.

For example, if you need to access the Product instance from the inside of the foreach: types loop, you could use the $parent property as shown below:

<tbody data-bind='foreach: shoppingCart'>
<tr>
.
.
<td>
<ul data-bind="foreach: types">
<li>
<span data-bind="text: $parent.name"></span> -
<span data-bind="text: $data"></span>
</li>
</ul>
</td>
.
.
</tbody data-bind='foreach: shoppingCart'>
</tr>

$parentContext

This refers to the binding context object at the parent level. This is different from $parent, which refers to the data (not binding context) at the parent level.

For example, if you need to access the index value of the outer foreach item with in inner foreach context you could use the $parentContext as shown below:

<tbody data-bind='foreach: shoppingCart'>
<tr>
.
.
<td>
<ul data-bind="foreach: types">
<li>
<span data-bind="text: $parentContext.$index"></span><span data-bind="text: $parent.name"></span> -
<span data-bind="text: $data"></span>
</li>
</ul>
</td>
.
.
</tbody data-bind='foreach: shoppingCart'>
</tr>

$parents

This is an array that represent all of the parent view models. This is useful when you need to access the parents with in inner most loops that may nested upto n-level.

$parents[0] is the view model from the parent context (i.e., it’s the same as $parent)

$parents[1] is the view model from the grandparent context

$parents[2] is the view model from the great-grandparent context

and so on.

Note

All the binding context properties are only available in the view, not in the ViewModel.

Example of Knockout Binding Context ($root,$data,$parent,$index)

<html lang='en'>
<head>
 <title>Knockout Binding Context</title>
 <style type="text/css">
 body
{
 margin: 20px;
 font-family: "Arial" , "Helventica" , sans-serif;
}

button
{
 display: inline-block;
 outline: none;
 cursor: pointer;
 text-align: center;
 text-decoration: none;
 padding: .4em 1.1em .4em;
 color: #fef4e9;
 border: solid 1px #006fb9;
 background: #1276bb;
 
}
button:hover
{
 text-decoration: none;
 background: #282828;
 border: solid 1px #000;
 }

table
{
 padding-top: 1em;
}

thead ,tfoot{
font-weight:600;

}
th, td
{
 padding: .1em .5em;
 text-align: left;
}

td li, td ul
{
 margin: 0;
 padding: 0;
}

td li
{
 display: inline;
}

td li::after
{
 content: ',';
}

td li:last-child::after
{
 content: '';
}

 </style>
</head>
<body>
 <h2>Knockout Binding Context</h2>
 <p><span data-bind="text:fullName"></span>'s Order</p>
 
 <button data-bind='click:addProduct'>Add Shampoo</button>
 <button data-bind='click:checkout'>Check Out</button>

 <table>
 <thead><tr>
 <th>Item number</th>
 <th>Product</th>
 <th>Price</th>
 <th>Types</th>
 <th>Action</th>
 </tr></thead>
 <tbody data-bind='foreach: shoppingCart'>
 <tr>
 <td data-bind='text: $index()+1'></td>
 <td data-bind='text: name'></td>
 <td data-bind='text: price'></td>
 <td>
 <ul data-bind="foreach: types">
 <li>
 <span data-bind="text: $parent.name"></span> - <span data-bind="text: $data"></span>
 </li>
 </ul>
 </td>
 
 <td>
 <button data-bind='click: $root.removeProduct'>Remove</button>
 </td>
 </tr>
 </tbody>
 <tfoot>
 <tr>
 <td></td>
 <td>Total :</td>
 <td data-bind="text: $root.total()"></td>
 <td></td>
 <td></th>
 </tr>
 </tfoot>
 </table>
 
 <script type='text/javascript' src='knockout-2.1.0.js'></script>
 <script type='text/javascript'>
 function Product(name, price, types) {
 var self = this;
 
 self.name = ko.observable(name);
 self.price = ko.observable(price);
 types = typeof (types) !== "undefined" ? types : []; //if empty then null
 self.types = ko.observableArray(types);
 }

 function PersonViewModel() 
 {
 
 var self = this;

 self.firstName = ko.observable("Saksham");
 self.lastName = ko.observable("Chauhan");
 self.fullName = ko.computed(function(){
 return self.firstName() + " " + self.lastName();
 }, this);

 self.shoppingCart = ko.observableArray([
 new Product("Soap", 10.99, ["Soft", "Hard"]),
 new Product("Shampoo", 7.99),
 new Product("Pickle", 15.49, ["Spicy", "Sweet"])
 ]);

 self.total = ko.computed(function(){
 var sum=0;
 var arr = self.shoppingCart();
 for (var i = 0; i < arr.length; i++) {
 sum += arr[i].price() ;
 }
 return sum;
 });
 
 self.addProduct = function () {
 self.shoppingCart.push(new Product("More Shampoo", 7.99));
 };

 self.removeProduct = function (product) {
 if(confirm('Are you sure to delete?'))
 {
 self.shoppingCart.remove(product);
 }
 
 };

 self.checkout = function () {
 var items = "";
 var arr = self.shoppingCart();
 for (var i = 0; i < arr.length; i++) {
 items += arr[i].name() + "\n"; // don't forget that you make a function call when accessing observable properties
 }
 alert(items);
 };
 
 };

 var vm = new PersonViewModel();
 ko.applyBindings(vm);
 </script>

</body>
</html>

Output

Adding Product to Order List

Remove Product from Order List

Checkout Order List

What do you think?

I hope you will enjoy the tips while working with Knockout. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

YOU MIGHT LIKE
Free Interview Books
 
COMMENTS (0)
14 DEC
ASP.NET MVC with AngularJS Development (online)

MON-FRI 07:30 AM- 09:00 AM IST

Know More
11 DEC
ASP.NET MVC with AngularJS Development (offline)

Sat-Sun 09:30 AM-11:00 AM IST

Know More
5 DEC
AngularJS Development (online)

Mon - Fri     6:30 AM-7:30 AM IST

3 DEC
AngularJS Development (offline)

SAT,SUN     11:00 AM-12:30 PM IST

3 DEC
MEAN Stack Development (offline)

Sat, Sun     (11:00 AM-12:30 PM IST)

26 NOV
ASP.NET MVC with AngularJS Development (offline)

(SAT,SUN)     03:30 PM-05:00 PM IST

24 NOV
ASP.NET MVC with AngularJS Development (online)

MON-FRI     09:30 PM-11:00 PM IST

12 NOV
ASP.NET MVC with AngularJS Development (offline)

SAT,SUN     08:00 AM-09:30 AM

3 NOV
ASP.NET MVC with AngularJS Development (online)

MON-FRI     07:30 AM-09:00 AM IST

25 OCT
.NET Development (offline)

Mon-Fri     9:00 AM-11:00 AM IST

BROWSE BY CATEGORY
 
RECENT ARTICLES
SUBSCRIBE TO LATEST NEWS
 
LIKE US ON FACEBOOK
 

Professional Speaks

+