You can control flow of element on the view using Control Flow bindings of Knockout.js. There are four Control Flow bindings

  • foreach binding
  • if binding
  • ifnot binding
  • with binding

Out of these four bindings foreach and if bindings are used very often.

foreach binding

foreach binding repeat same markup for number of times equivalent to number of elements in an array. It also binds each repeat of mark-up to corresponding item of the array.

image

Let us try to understand it with an example. Assume we have a ViewModel which contains observable array as one of the observable.


var viewModel =
 {
 students: ko.observableArray
 ([
 {name :"Dan W", subject : "JavaScript" },
 { name: "Glenn B", subject: "Node" },
 { name: "Pinal D", subject: "SQL" }
 ])
 }

ViewModel contains a property students which is an observable array. We can bind this on view to a table or lists elements.


<table>
 <thead>
 <tr>
 <th>Name</th>
 <th>Subject</th>
 </tr>
 </thead>
 <tbody data-bind="foreach: students">
 <tr>
 <td data-bind="text: name"></td>
 <td data-bind="text: subject"></td>
 </tr>
 </tbody>
 </table>

As you notice that on the table body we are performing foreach binding. So mark-up inside table body would be repeated 3 times in this case. Since number of elements in observable array is 3.

On running this application you will get table rendered with three rows as below,

image

Next let us consider one complex scenario in which we want to add and remove students. So let us go ahead an update view model with computed observable to add and remove items from observable array


function viewModel()
 {
 var self=this;
 self.students= ko.observableArray
 ([
 {name :"Dan W", subject : "JavaScript" },
 { name: "Glenn B", subject: "Node" },
 { name: "Pinal D", subject: "SQL" }
 ]);
 self.addStudent= function ()
 {
 self.students.push({ name: "dj", subject: "JavaScript" });
 };
 self.removeStudent= function ()
 {
 self.students.remove(this);
 }
 }

ko.applyBindings(new viewModel());

There is nothing much fancy in above ViewModel. We just added computed observables to add and remove students. Next we can bind that to a view contains unordered list as below


<h4>Students</h4>
 <ul data-bind="foreach: students">
 <li>Name at position <span data-bind="text: $index"></span>:
 <span data-bind="text: name"></span>
 <a href="#" data-bind="click: $parent.removeStudent">Remove</a>
 </li>
 </ul>
 <button data-bind="click: addStudent">Add</button>

On running application you will find that now you can add and remove student

image

You can use $index, $parent, $data with foreach binding as well. For example

  • You can read index of a particular element using $index.
  • You can read array element using $data. Not a particular element
  • You can read parent viewmodel or other properties of viewmodel using $parent

if binding

if binding allows whether a section of mark-up will appear or not. Unlikely visible binding if binding add or remove markup from the DOM. It performs following tasks,

  • Add or remove markup from the DOM
  • Make sure that data-bind attribute is having applied on the markup

Now let us take if binding in action. Let us say you have ViewModel as below


var viewModel =
 {
 show : ko.observable(false)
 }

ko.applyBindings(viewModel);

On View we can do binding as follows


<label><input type="checkbox" data-bind="checked: show" />Display Div</label>
<div data-bind="if: show">Visible/Hide using if binding </div>

As you notice that we are doing checked binding on input checkbox whereas performing if binding on div. If value of ViewModel property evaluates to non-false value then then div would be visible. Input is toggling value of show property.

Let us take another example in which we will learn that how if binding is useful in case of working with null. As you know if binding add or removes elements on the DOM having their data binding applied on that. Consider following ViewModel


function viewModel() {
 var self = this;
 self.students = ko.observableArray
 ([
 { name: "Dan W", subject: null },
 { name: "Glenn B", subject: { music: 'guitar' } },
 { name: "Pinal D", subject: { music: 'drum' } }
 ]);

};

Next we need to do if binding on the view,


<h4>Students</h4>
 <ul data-bind="foreach: students">
 <li>
 Student: <b data-bind="text: name"> </b>
 <div data-bind="if: subject">
 Subject: <b data-bind="text: subject.music"> </b>
 </div>
 </li>
</ul>

Above you see that we are applying if binding on div going to display subject. If binding add or remove on basis of non-falsie value. So for student subject value is set to null this div will not get created. If you try to achieve it using visible binding then for any student for which value if subject is set to null you will get subject.music throwing exception.

Ifnot binding

This is exactly the same as if binding. it only inverts the value passed to it.

So let us say you have ViewModel as below,


var viewModel =
 {
 display : ko.observable(false)
 }

and you bind this to a view as given below,


<div data-bind="ifnot: display">
 <h1>hello</h1>
 </div>

On running you will find div is added on the DOM even though display property in ViewModel is set to false. Because ifnot binding invert value of property in ViewModel.

When you create MVVM application using Knockout.js , control flow binding is very useful. You will use it very often and I hope you find this post useful in understanding control flow binding. Thanks for reading.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s