The bare bone code of a KnockoutJS application
I'm sure you have seen a lot of web applications with all the JavaScript code in the main HTML page. As a web developer, I suggest you avoid this kind of behavior.
Tip
A good practice when you develop any web application is to divide the visual code (HTML) from the scripting code; one reason is that HTML pages are hard to test, and if you fill them with inner code you will have a hard time fixing bugs caused by JavaScript.
There are different ways to organize your code, and in another chapter, we will look at how can you use the RequireJS library to modularize it; but just now, for this first simple application, we don't need the overhead that library introduces.
Here, we will put all the HTML pages in the root folder, the style sheet files in a folder named css
, and all the JavaScript inside a js
folder.
Let's start making a folder called SimpleShowCase
, with these sub-folders:
js
images
Then, in the SimpleShowCase
folder,
create the following files:
index.html
js/index.js
You can save empty files just now, or, if you are using a Unix-like OS you can use the program, touch
, in this way:
touch SimpleShowCase/index.html
You must also put the downloaded library, knockout.js
, as SimpleShowCase/js/knockout.js
(download it now if you skipped this step before).
On Windows, you should have something like this:
If you have a Unix-like system (Linux, Mac OS X), you should have a structure like this:
Finally, download from the website the StartingPackage.zip
for this chapter, and decompress it in the SimpleShowCase
folder; you'll get all the images and a style sheet file realized by our designer.
Now, we can start with the code for the index page; put this starting markup into index.html
:
<!DOCTYPE html> <html> <head> <title>Jewelry Show Case</title> <link rel="stylesheet" href="css/styles.css" /> </head> <body> <h1>Welcome to our Jewelry collection.</h1> <h2>Can you find anything interesting?</h2> <div data-bind="foreach: jewels"> <div class="jewel"> <span data-bind="text: name"></span> <img data-bind="attr: { src: src }"> </div> </div> <script type="text/javascript" src="js/knockout.js"></script> <script type="text/javascript" src="js/index.js"></script> </body> </html>
Here, we are asking the browser to:
- Load the stylesheet file
- Create a really simple DOM structure
- Load the KnockoutJS library and
js/index.js
, which contains our application code.
On this page, we put three different kind of data-binding attributes from the standard codebase of KnockoutJS: foreach, text, and attr.
The details about these binding handlers are as follows:
foreach
: This is used with an array property and replicates the DOM structure inside the node it is applied to; it creates a node for each item in the array and assigns the context to the specific item; for example, in our application, for each jewel adiv
element is createdtext
: This binds to theinnerText
data of the nodeattr
: This is a hash map and binds every item inside it to the property of the node
Our view is ready, but if you try to look at the application with a web browser you'll find that nothing magical is going on. The reason is that we need another major step to get everything working: applying the bindings.
So, now we go to our application code in js/index.js
and we put these lines:
var myViewModel = { jewels: ko.observableArray([ { name: "White Bracelet", src: "images/bracelet_1_big_1.png" }, { name: "Tear Earring", src: "images/earring_1_big_1.png" }, { name: "Gold Necklace", src: "images/necklace_1_big_1.png" }, { name: "Marriage Ring", src: "images/ring_2_big_1.png" } ]) }; ko.applyBindings(myViewModel);
Here, we are making our View Model object (nothing more than a normal JavaScript object, defined with the object literal syntax) with only one property: jewels
.
The value of the property is ko.observableArray()
; this is a helper inside the ko namespace that KnockoutJS gives us to create observable properties for the array type. You can get much more information about it at this link: http://knockoutjs.com/documentation/observables.html.
The value you pass into the call to ko.observableArray
is the starting value of this object; here, we are creating it with an array with four items.
Note
The ko.observableArray
value is an implementation of the Decorator design pattern. In fact, it decorates your array with some logic to detect the changes (while implementing the Observable design pattern).
Anyway, the true magic of KnockoutJS starts with the next row:
ko.applyBindings(myViewModel);
In the next section, we will see what this function does in depth, but now, to get some code running, we can simply say it binds the view model object with the DOM.