Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon

Text and appearance bindings and form field bindings

Save for later
  • 14 min read
  • 25 May 2015

article-image

In this article by Andrey Akinshin, the author of Getting Started with Knockout.js for .Net Developers, we will look at the various binding offered by Knockout.js. Knockout.js provides you with a huge number of useful HTML data bindings to control the text and its appearance. In this section, we take a brief look at the most common bindings:

  • The text binding
  • The html binding
  • The css binding
  • The style binding
  • The attr binding
  • The visible binding

(For more resources related to this topic, see here.)

The text binding

The text binding is one of the most useful bindings. It allows us to bind text of an element (for example, span) to a property of the ViewModel. Let's create an example in which a person has a single firstName property.

The Model will be as follows:

var person = {
firstName: "John"
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.firstName = ko.observable(person.firstName);
};

The View will be as follows:

The first name is <span data-bind="text: firstName"></span>.

It is really a very simple example. The Model (the person object) has only the firstName property with the initial value John. In the ViewModel, we created the firstName property, which is represented by ko.observable. The View contains a span element with a single data binding; the text property of span binds to the firstName property of the ViewModel. In this example, any changes to personViewModel.firstName will entail an automatic update of text in the span element. If we run the example, we will see a single text line: The first name is John.

Let's upgrade our example by adding the age property for the person. In the View, we will print young person for age less than 18 or adult person for age greater than or equal to 18 (PersonalPage-Binding-Text2.html):

The Model will be as follows:

var person = {
firstName: "John",
age: 30
};

The ViewModel will be as follows:

var personViewModel = function() {
var self = this;
self.firstName = ko.observable(person.firstName);
self.age = ko.observable(person.age);
};

The View will be as follows:

<span data-bind="text: firstName"></span> is <span data- bind="text: age() >= 18 ? 'adult' : 'young'"></span>   person.

This example uses an expression binding in the View. The second span element binds its text property to a JavaScript expression. In this case, we will see the text John is adult person because we set age to 30 in the Model.

Note that it is bad practice to write expressions such as age() >= 18 directly inside the binding value. The best way is to define the so-called computed observable property that contains a boolean expression and uses the name of the defined property instead of the expression. We will discuss this method later.

The html binding

In some cases, we may want to use HTML tags inside our data binding. However, if we include HTML tags in the text binding, tags will be shown in the raw form. We should use the html binding to render tags, as shown in the following example:

The Model will be as follows:

var person = {
about: "John's favorite site is <a     href='http://www.packtpub.com'>PacktPub</a>."
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.about = ko.observable(person.about);
};

The View will be as follows:

<span data-bind="html: about"></span>

Thanks to the html binding, the about message will be displayed correctly and the <a> tag will be transformed into a hyperlink. When you try to display a link with the text binding, the HTML will be encoded, so the user will see not a link but special characters.

The css binding

The html binding is a good way to include HTML tags in the binding value, but it is a bad practice for its styling. Instead of this, we should use the css binding for this aim. Let's consider the following example:

The Model will be as follows:

var person = {
favoriteColor: "red"
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.favoriteColor = ko.observable(person.favoriteColor);
};

The View will be as follows:

<style type="text/css">
.redStyle {
   color: red;
}
.greenStyle {
   color: green;
}
</style>
<div data-bind="css: { redStyle: favoriteColor() == 'red',   greenStyle: favoriteColor() == 'green' }">
John's favorite color is <span data-bind="text:   favoriteColor"></span>.
</div>

In the View, there are two CSS classes: redStyle and greenStyle. In the Model, we use favoriteColor to define the favorite color of our person. The expression binding for the div element applies the redStyle CSS style for red color and greenStyle for green color. It uses the favoriteColor observable property as a function to get its value. When favoriteColor is not an observable, the data binding will just be favoriteColor== 'red'. Of course, when favoriteColor changes, the DOM will not be updated because it won't be notified.

The style binding

In some cases, we do not have access to CSS, but we still need to change the style of the View. For example, CSS files are placed in an application theme and we may not have enough rights to modify it. The style binding helps us in such a case:

The Model will be as follows:

var person = {
favoriteColor: "red"
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.favoriteColor = ko.observable(person.favoriteColor);
};

The View will be as follows:

<div data-bind="style: { color: favoriteColor() }">
John's favorite color is <span data-bind="text:   favoriteColor"></span>.
</div>

This example is analogous to the previous one, with the only difference being that we use the style binding instead of the css binding.

The attr binding

The attr binding is also a good way to work with DOM elements. It allows us to set the value of any attributes of elements. Let's look at the following example:

The Model will be as follows:

var person = {
favoriteUrl: "http://www.packtpub.com"
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.favoriteUrl = ko.observable(person.favoriteUrl);
};

The View will be as follows:

John's favorite site is <a data-bind="attr: { href: favoriteUrl()   }">PacktPub</a>.

The href attribute of the <a> element binds to the favoriteUrl property of the ViewModel via the attr binding.

The visible binding

The visible binding allows us to show or hide some elements according to the ViewModel. Let's consider an example with a div element, which is shown depending on a conditional binding:

The Model will be as follows:

var person = {
favoriteSite: "PacktPub"
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.favoriteSite = ko.observable(person.favoriteSite);
};

The View will be as follows:

<div data-bind="visible: favoriteSite().length > 0">
John's favorite site is <span data-bind="text:   favoriteSite"></span>.
</div>

In this example, the div element with information about John's favorite site will be shown only if the information was defined.

Form fields bindings

Forms are important parts of many web applications. In this section, we will learn about a number of data bindings to work with the form fields:

  • The value binding
  • The click binding
  • The submit binding
  • The event binding
  • The checked binding
  • The enable binging
  • The disable binding
  • The options binding
  • The selectedOptions binding

The value binding

Very often, forms use the input, select and textarea elements to enter text. Knockout.js allows work with such text via the value binding, as shown in the following example:

The Model will be as follows:

var person = {
firstName: "John"
};

The ViewModel will be as follows:

Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
var PersonViewModel = function() {
var self = this;
self.firstName = ko.observable(person.firstName);
};

The View will be as follows:

<form>
The first name is <input type="text" data-bind="value:     firstName" />.
</form>

The value property of the text input element binds to the firstName property of the ViewModel.

The click binding

We can add some function as an event handler for the onclick event with the click binding. Let's consider the following example:

The Model will be as follows:

var person = {
age: 30
};

The ViewModel will be as follows:

var personViewModel = function() {
var self = this;
self.age = ko.observable(person.age);
self.growOld = function() {
   var previousAge = self.age();
   self.age(previousAge + 1);
}
};

The View will be as follows:

<div>
John's age is <span data-bind="text: age"></span>.
<button data-bind="click: growOld">Grow old</button>
</div>

We have the Grow old button in the View. The click property of this button binds to the growOld function of the ViewModel. This function increases the age of the person by one year. Because the age property is an observable, the text in the span element will automatically be updated to 31.

The submit binding

Typically, the submit event is the last operation when working with a form. Knockout.js supports the submit binding to add the corresponding event handler. Of course, you can also use the click binding for the "submit" button, but that is a different thing because there are alternative ways to submit the form. For example, a user can use the Enter key while typing into a textbox.

Let's update the previous example with the submit binding:

The Model will be as follows:

var person = {
age: 30
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.age = ko.observable(person.age);
self.growOld = function() {
   var previousAge = self.age();
   self.age(previousAge + 1);
}
};

The View will be as follows:

<div>
John's age is <span data-bind="text: age"></span>.
<form data-bind="submit: growOld">
   <button type="submit">Grow old</button>
</form>
</div>

The only new thing is moving the link to the growOld function to the submit binding of the form.

The event binding

The event binding also helps us interact with the user. This binding allows us to add an event handler to an element, events such as keypress, mouseover, or mouseout. In the following example, we use this binding to control the visibility of a div element according to the mouse position:

The Model will be as follows:

var person = {
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.aboutEnabled = ko.observable(false);
self.showAbout = function() {
   self.aboutEnabled(true);
};
self.hideAbout = function() {
   self.aboutEnabled(false);
}
};

The View will be as follows:

<div>
<div data-bind="event: { mouseover: showAbout, mouseout:     hideAbout }">
   Mouse over to view the information about John.
</div>
<div data-bind="visible: aboutEnabled">
   John's favorite site is <a       href='http://www.packtpub.com'>PacktPub</a>.
</div>
</div>

In this example, the Model is empty because the web page doesn't have a state outside of the runtime context. The single property aboutEnabled makes sense only to run an application. In such a case, we can omit the corresponding property in the Model and work only with the ViewModel. In particular, we will work with a single ViewModel property aboutEnabled, which defines the visibility of div. There are two event bindings: mouseover and mouseout. They link the mouse behavior to the value of aboutEnabled with the help of the showAbout and hideAbout ViewModel functions.

The checked binding

Many forms contain checkboxes (<input type="checkbox" />). We can work with its value with the help of the checked binding, as shown in the following example:

The Model will be as follows:

var person = {
isMarried: false
};

The ViewModel will be as follows:

var personViewModel = function() {
var self = this;
self.isMarried = ko.observable(person.isMarried);
};

The View is as follows:

<form>
<input type="checkbox" data-bind="checked: isMarried" />
Is married
</form>

The View contains the Is married checkbox. Its checked property binds to the Boolean isMarried property of the ViewModel.

The enable and disable binding

A good usability practice suggests setting the enable property of some elements (such as input, select, and textarea) according to a form state. Knockout.js provides us with the enable binding for this purpose. Let's consider the following example:

The Model is as follows:

var person = {
isMarried: false,
wife: ""
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.isMarried = ko.observable(person.isMarried);
self.wife = ko.observable(person.wife);
};

The View will be as follows:

<form>
<p>
   <input type="checkbox" data-bind="checked: isMarried" />
   Is married
</p>
<p>
   Wife's name:
   <input type="text" data-bind="value: wife, enable: isMarried" />
</p>
</form>

The View contains the checkbox from the previous example. Only in the case of a married person can we write the name of his wife. This behavior is provided by the enable binding of the text input element.

The disable binding works in exactly the opposite way. It allows you to avoid negative expression bindings in some cases.

The options binding

If the Model contains some collections, then we need a select element to display it. The options binding allows us to link such an element to the data, as shown in the following example:

The Model is as follows:

var person = {
children: ["Jonnie", "Jane", "Richard", "Mary"]
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.children = person.children;
};

The View will be as follows:

<form>
<select multiple="multiple" data-bind="options:     
children"></select> </form>

In the preceding example, the Model contains the children array. The View represents this array with the help of multiple select elements. Note that, in this example, children is a non-observable array. Therefore, changes to ViewModel in this case do not affect the View. The code is shown only for demonstration of the options binding.

The selectedOptions binding

In addition to the options binding, we can use the selectedOptions binding to work with selected items in the select element. Let's look at the following example:

The Model will be as follows:

var person = {
children: ["Jonnie", "Jane", "Richard", "Mary"],
selectedChildren: ["Jonnie", "Mary"]
};

The ViewModel will be as follows:

var PersonViewModel = function() {
var self = this;
self.children = person.children;
self.selectedChildren = person.selectedChildren
};

The View will be as follows:

<form>
<select multiple="multiple" data-bind="options: children,     
selectedOptions: selectedChildren"></select> </form>

The selectedChildren property of the ViewModel defines a set of selected items in the select element. Note that, as shown in the previous example, selectedChildren is a non-observable array; the preceding code only shows the use of the selectedOptions binding. In a real-world application, most of the time, the value of the selectedChildren binding will be an observable array.

Summary

In this article, we have looked at examples that illustrate the use of bindings for various purposes.

Resources for Article:


Further resources on this subject: