Adding the application features
Our address book application captures, stores, and displays contacts details of our family and friends.
Capturing and storing contacts
Let's develop the functionality to capture and store the contacts. The two pieces of information we want to capture and store is the contact name and phone number. This is defined as a model in our AddressBook module. To do this, open the addressbook.js file and add the following code:
The code defines a contact object with two attributes—name and phoneNumber. The attributes are Knockout observables. We will bind the contact object to our HTML input fields to capture user input. Before we add the HTML fields and the binding construct, we need to expose the contact object publicly so that it can be accessed outside our module, for example, by our HTML binding construct. This is done by adding the contact object to the return statement of our module. Let's add the contact object to the return statement. Here is what the code should be:
Let's now add the HTML input fields to our view and bind them to our view model. Open addressbook.html and the following code in the body of the HTML; take this opportunity to also change the title of the HTML page to something more appropriate like Knockout: Address Book Example:
In the preceding code, we have declared two HTML input fields, one for the contact name and the other for the contact phone number. We also added the binding construct by using data-bind. Notice the way we accessed the model. For example, to access the name attribute of the contact, we used the name of our module, AddressBook; followed by the name of our model object, contact; followed by the name of the attribute, name.
The capturing of user input is not complete without a button to indicate that the user has entered a new contact. Add a button to your HTML by inserting the following line after the input text fields:
The preceding code will add a button to your view with the Add label. It also adds a click binding. As a result of the click binding, an addContact function will get executed when the user clicks on the Add button. We have not yet defined the addContact method. Let's do this by adding the following code to our view model:
The code displays the values of contact name and phone number from the contact object in the browser console. Notice how we access the value of the name and phoneNumber observables. The addContact method needs to be publicly accessible as it is referenced in our view. Let's do this by adding it to the return statement of our module. Our return statement should now look similar to this:
We are missing one very important step before we can run what we have developed so far. That step is to activate Knockout. Add the following line of code to the init function in our module:
Here, the applyBindings function takes view model as the parameter and applies the bindings declared in our view to the model and behavior, defined in our view model. We pass the view model to the applyBindings function by passing our AddressBook module.
Now that our application is capturing the contact details, let's develop the functionality to store the contacts. The contacts will be stored using an array. We cannot use the normal JavaScript array as we will need to bind the array to our view in order to display the contacts. Knockout provides a way to construct an array of observables. To make an array of contacts, add the following code to our AddressModule below the contact:
The observableArray function returns an object, which can track the objects it holds. This means that any subscriber will be notified when an object is added or removed from it.
Note
The members of the objects that observableArray hold, do not become observables. This, however, can be achieved through additional code.
Now that we have declared our contacts array, let's add the contact to our contacts array. Modify the addContact function and add the following line of code to push a contact to the contacts array. Your addContact function should look similar to this:
Knockout observableArray provides useful methods to interact with the array. We have used a method push, which insets a new item at the end of the array. We pass a new contact object to the push method by creating an object with name and phone number as attributes. The value of the attributes come from our name and phoneNumber observables in the contact object.
You may have noticed that the input fields for name and phone numbers retain their values after the add button is clicked and the object is added to the contacts array. This is not for user experience as the user has to clear the inputs before a new contact can be added. To clear the input fields, add the following method to your AddressBook module:
Call this method from your addContact method after pushing the new contact to the contacts array. The clearContact method clears the values of the name and phoneNumber observable by setting them to null. The two-way data binding takes care of updating the HTML input fields. You do not have to add the clearContact method to the return statement of the module as this a private member, which is not required by any other external module or view.
So far, we have:
- Developed our application skeleton
- Created our view with two HTML input text fields for capturing contact name and phone number, and a button to allow user to add a contact
- Created our module with a model for capturing the user input and storing contacts in an array
- Added functionality to add the contact to the contacts array and clear the input fields
- Added declarative binding to our view to bind the HTML input fields to the contact object and the
Add button to the addContact function in our view model - Activated Knockout by calling the
applyBindings function in our init function
Let's run our application and see what happens. Open
addressbook.html in a browser. Don't forget to open the console window of the browser. Try adding a contact.
Note
You can open the console window in Chrome by hitting the F12 key and selecting Console in the menu bar.
The application should look similar to this:
The next application feature we will add to our address book application is displaying the list of contacts in a table. We will use the HTML table element with foreach binding. Let's get straight into it.
Open the addressbook.html file and add the following code under the input HTML fields:
In the preceding code, we are using the foreach binding to repeatedly render a table row of contacts. The foreach binding provides a loop construct to display HTML elements based on a template. The HTML markup within the tbody element is used as the template to render each contact.
The data binding declaration in the preceding code refers to the contacts array in our module. We have not yet declared the contacts array to be publicly accessible. Make the contacts array publicly accessible by adding it to the return statement of your module. The return statement of AddressBook module should look similar to this:
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.
Run the application by opening addressbook.html in a browser. Try adding some contacts. You should now be able to see the newly added contacts displayed in the table. The application should look similar to this: