Binding DOM elements using Knockout
There are two basic ways to bind your View elements to the ViewModel. You can either bind it through the element data-bind
attribute or by using friendly code in JavaScript. Let's begin by creating a page in the \ko\ko-1\do\
folder using the name binding.htm
. The following is the basic standard code for your do
pages throughout the book:
<!DOCTYPE html> <html lang="en"> <head> </head> <body> <script src="/share/js/knockout.js"></script> <script type="text/javascript"> var viewModel = { } ko.applyBindings(viewModel); </script> </body> </html>
Tip
Downloading the example code
You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
The first part of using Knockout is to include the library JS file. Then we need to create the ViewModel. At this time, the ViewModel is similar to a class file as it does not do anything until we bind it using Knockout's applyBindings
method. The name of the Model does not matter to Knockout as long, of course, as it does not conflict with JS or some other currently running library.
Binding text
To bind the text to the ViewModel, use the following steps:
- Add the following code to the ViewModel:
var viewModel = { myVariable: ko.observable()}
- We will use the
data-bind
attribute to tell Knockout how to bind our data through the ViewModel. We bind the text attribute of this DOM element to the ViewModel variablemyVariable
. After thebody
tag, add this code:My first KnockoutJS uses text binding: <span data-bind="text: myVariable"></span> <hr>
- We are now ready to run the code. When you look at the code in the browser nothing appears to happen. That is because there is no value assigned to the ViewModel variable, so nothing gets injected into the View. It gives us the following text in the browser window:
- Let's add one more line below the line where we bind the ViewModel in our script:
ko.applyBindings(viewModel); viewModel.myVariable("Awesome simple!");
The code gives us a value to be assigned, and when we run the page it shows the data bound to the DOM element. The following text is the output in the browser window:
Here, we see that the text attribute of the HTML DOM element updated when the variable was updated. There was no need to directly update the HTML DOM element as the ViewModel feature of Knockout automates this feature. In large and complex data sets, Knockout has been tested as the fastest data bound library. Of course, this consideration might change over time.
Binding HTML
To bind HTML to the ViewModel use the following steps:
- Add the HTML code to the ViewModel:
var viewModel = { myVariable: ko.observable(), myHTML: ko.observable() }
- Set the value of the
myHTML
variable after the binding of the ViewModel:viewModel.myVariable("Awesome simple!"); viewModel.myHTML("<strong>Awesome</strong> simple!");
- Now, we need to bind the HTML attribute of the DOM element. As you can see, the syntax is very similar to the text binding we used in the last binding:
My second KO uses HTML binding: <div data-bind="html: myHTML"></div> <hr>
If we pass HTML through to the text element, it does not display correctly, and that is why DOM has a particular HTML attribute for appropriate tags. When we use the text approach, Knockout escapes the results and using HTML, places the results the way it would look in an editor. The HTML attribute does not exist every time the text attribute exists, but it is pretty safe to assume that the text does exist any time we find the HTML at this point. When we render again, Knockout renders the text as shown here:
Binding CSS
To bind CSS to the ViewModel go through the following steps:
- Add the myLeft and myRight variables to the ViewModel:
var viewModel = { myVariable: ko.observable() ,myHTML: ko.observable() ,myLeft: ko.observable() ,myRight: ko.observable() }
- Set the values of the
myLeft
andmyRight
variables after the binding of the ViewModel:viewModel.myVariable("Awesome simple!"); viewModel.myHTML("<strong>Awesome</strong> simple!"); viewModel.myLeft("pullLeft"); viewModel.myRight("pushRight");
- Use the CSS attribute to the
data-bind
setting to manage CSS dynamically through the ViewModel. This could be changed at any time, and the elements would reflect the CSS settings based on how, of course, the individual browser responds to those CSS settings.<div data-bind="css: myLeft">LEFT </div> <div data-bind="css: myRight"> RIGHT</div> My third KO uses CSS binding: <hr>
When we render again, Knockout renders the text as shown here:
Binding numbers
The following steps will explain how to bind numbers to the ViewModel:
- Add the following code to the ViewModel:
var viewModel = { myVariable: ko.observable() ,myHTML: ko.observable() ,myLeft: ko.observable() ,myRight: ko.observable() ,myBalance: ko.observable() }
- Set the value of the
myBalance
variable after the binding of the ViewModel:viewModel.myVariable("Awesome simple!"); viewModel.myHTML("<strong>Awesome</strong> simple!"); viewModel.myLeft("pullLeft"); viewModel.myRight("pushRight"); viewModel.myBalance(-47.23);
Here, we explore our first data-bind
where we are binding to more than one setting at the same time via the HTML markup. Notice that we also wrapped the element with an additional outer element to allow us to set the color for the balance based on whether it is negative or not. When we are doing this, we can insert a bit of JavaScript into the setting. When using JavaScript, we refer to myBalance
as a function and not as a variable because that is how we interact with it in JavaScript. Take a look at the following code:
My fourth KO uses Style binding:<br> Balance = <span data-bind="style: { color: myBalance() < 0 ? 'red' : 'black' }"><span data-bind="text:myBalance"></span></span> <hr>
When we render again, Knockout renders the text as shown here:
Managing visibility
To manage visibility of the elements in the ViewModel, use the following steps:
- Add the following code to the ViewModel:
var viewModel = { myVariable: ko.observable() ,myHTML: ko.observable() ,myLeft: ko.observable() ,myRight: ko.observable() ,myBalance: ko.observable() ,isVisible: ko.observable() }
- Set the value of the
isVisible
variable after the binding of the ViewModel:viewModel.myVariable("Awesome simple!"); viewModel.myHTML("<strong>Awesome</strong> simple!"); viewModel.myLeft("pullLeft"); viewModel.myRight("pushRight"); viewModel.myBalance(-47.23); viewModel.isVisible(true);
- Scripting can be a very powerful technique to use as your skills with Knockout advance. It can add a sense of automation and value to the user experience. Insert the following code after the
body
tag:My fifth KO uses visible binding: <div data-bind="visible: isVisible">Warning, the visible property is set to true.</div> <hr>
When we render again, Knockout renders the text as shown here. Try, of course, changing the value to false
and run it again to see that it is working correctly for you.
Multibound control
The ViewModel does not need to be updated this time as the technique we are discussing is managed from the HTML DOM element side. We need to set the value of the data-bind
variable for both color and text as follows:
viewModel.myVariable("Awesome simple!");
viewModel.myHTML("<strong>Awesome</strong> simple!");
Here, we explore our first data-bind
where we are binding to more than one setting at the same time via the HTML markup. Using the bracketed form, we nest a slight amount of JavaScript right into the markup. Again, keep in mind that when you are using the JavaScript functionality you have to deal with the ViewModel attribute as a function and not as a variable. It is good to watch out for this as it is a common thing for new Knockout developers to overlook. Here is the code to add after the body
tag:
My sixth KO uses multi-binding: Balance = <span data-bind="style: { color: myBalance() < 0 ? 'red' : 'black' },text:myBalance"></span>
When we render again, Knockout renders the text shown here:
Try changing the number and running it to get the number to show both black and red depending, of course, on having the right number setting in the code. You could even change the logic if you choose to.