Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
KnockoutJS Web Development

You're reading from  KnockoutJS Web Development

Product type Book
Published in Feb 2015
Publisher
ISBN-13 9781782161028
Pages 178 pages
Edition 1st Edition
Languages

Chapter 4. Coding – AJAX, Binding Properties, Mapping, and Utilities

There is an aspect of Knockout that takes repeated tasks out of the way. There is also the reality that we never expect it to do 100 percent of our work. It also makes sense that we do not have Knockout doing so much as it is not good at its core strengths. Here, we will learn how to extend our reach into Knockout and how to connect to the world outside Knockout and do even more. This chapter will focus on:

  • Working with JSON

  • Mapping versus manual ViewModels

  • Working with AJAX requests

  • Unmapping your data

  • Managed mapping

  • Utility functions

In this chapter, we will be learning about some of the commonly used aspects of Knockout—working with JSON and the mapping plugin. These two are simple and powerful pivots where we will extend rapid application development with Knockout.

JSON done Knockout style


JSON is the famous data packaging standard that seems to have taken over the Internet. At one time there was XML; RoR has its own packaging standard; and even Adobe had perhaps the best performing way to package and deliver data between the client and the server called Action Message Format (AMF). The overall winner seems to be JSON because it is simple and based on the most common development platform of all: JavaScript. If you would like more information about JSON you can visit http://json.org.

To serve our purpose, let's create a file called, json.html. The first thing we will do is convert a ViewModel to JSON. Most modern browsers have a function called JSON.stringify but that is not how we do it in Knockout. There are two methods included in Knockout:

  • ko.toJS

  • ko.toJSON

The first method, ko.toJS, will clone the Knockout data into a plain copy that contains no Knockout-related hints or information. The second method, ko.toJSON, will perform the ko.toJS action...

Mapping – first look


We have been creating manual maps of our ViewModel so far in this book. With smaller datasets this can be practical and productive. As our datasets get larger along with the need to update the data, this will become a chore that has an alternative, enjoyed by a great number of Knockout developers. This is done through a mapping plugin. Knockout is a jQuery-based library in more than one way. It is possible to build and use libraries, called plugins, for Knockout also. The most famous library is the mapping library. I have included a copy of it in the downloaded files for this book. We will be looking again at the preceding code for our example but moving it this time using the mapping plugin.

We will create a file called mapping.html for our code this time. We will need to include one more JavaScript file right after the Knockout call for our mapping plugin. You can find these files in the working examples folder in the ZIP download. This, in our case, should look like...

Connecting with AJAX remotely


Using a script tag to load data is definitely not very sophisticated. We are going to improve this by creating the example again, but this time using jQuery to make our AJAX request. We will put this code in a file named ajax.html. We will use the same HTML code as before, but we will add a button to the form using the following lines of code:

Foods (<span data-bind="text: foods"></span>)
<button data-bind="click: pullData">Pull Data</button><br/>
<div data-bind="foreach: {data:foodItems, as: 'food'}">
  <input type="checkbox" data-bind="checkedValue:$data.item, checked: $root.foods" />
  <span data-bind="text: food.itemDisplay"></span><br/>
</div>

The pullData request will be a method/function that we add to our ViewModel. It will be used, at this time, to pull the data from the server and update the View in our browser. Here is the script section of code we will use for this example:

<script...

Unmapping your data


This is coming along good but there is something we are going to need for most AJAX-based web applications. We are going to need to store the data back on the server. Pulling the data to the browser will not be enough. We will require the ability to push the data back to the server as well. Once again, we will be using jQuery for this function. Of course, we will show the code to do this but we will approach it differently because different readers will be using different backends such as ASP.NET, ColdFusion, Node.js, PHP, Python, Ruby, and others.

This time, just modify the code in the AJAX.html file unless, of course, you want to create a new file. We will be adding another button to our View to connect a push data method this time:

<button data-bind="click:pushData">Push Data</button>

We will also need to put a textbox at the end of our View code to see the data that is pulled out of our ViewModel. Create the textarea field to hold the results:

<textarea...

Merging mapped data


There are times you may want to pull data into your ViewModel from multiple sources. When doing this you can create a map for each source. If the source variables have the same name they will overwrite the existing variables. As long as the base variable is a different name it will merge them into the ViewModel. Do this as follows:

myViewModel = ko.mapping.fromJS(firstData, firstMap);
ko.mapping.fromJS(nextData, nextMap, myViewModel);

What you get is a combination of the firstData JavaScript structure, mapped with firstMap, combined with the nextData JavaScript structure, and with the nextMap mapping. If there are any duplicate base structures in nextData, they will override the same structures in the existing firstData JavaScript structure.

Mapping options


There are times when you are loading data into a page application that doesn't need to be changed. This is just static data and making it observable spends extra processor time and memory resources for no gain. When passing data into the mapping handler, you can set which items are mapped as observable items, using the following lines of code:

var data = {
  a: "a",
  b: [{ b1: "v1" }, { b2: "v2" }],
  c: true
};
var result = ko.mapping.fromJS(data, { observe: "a" });
var result2 = ko.mapping.fromJS(data, { observe: "a", copy: "b" }); //will be faster to map.

The results we get from the result and result2 variables will be the same. Why? This is because when we declare the observe items the other items are assumed to be copied items. If a single item is passed in we can declare it outside an array, as we did with a. If multiple items are passed in we would declare them in an array, as ["a","c"]. This would make both a and c observable items.

If we just wanted to declare an item...

Utility functions


There are a number of functions in ko.utils. Let's start by looking at the special array methods in standard Knockout.

ko.utils.arrayFilter()

The ko.utils.arrayFilter function allows us to filter items in an array. We are going to run these as straight code examples. We will create a sample JSON file and load it via AJAX to keep the focus on learning the methods and not waste time creating an example code set. We will create a page called utility.html for these pieces of code and run the filtering code from there. Our markup for this example is here:

<h3>arrayFilter() : staff under 35</h3>
<ul data-bind="foreach: youngStaff">
  <li><span data-bind="text: age() + ' ' + firstName()"></span></li>
</ul>

Our script code is as follows. We will be adding more for each example as we go, but here are the basics for the utility examples:

<script>
var vm = {};
jQuery.getJSON('utility.json').done(function(data){
  vm = ko.mapping.fromJS...

Purifying our computations


Now we are going to redo the script section of code using pureComputed versus computed. The term pureComputed was inspired by the concept of pure functions as a style of programming. It is nothing you need to understand to use so don't get caught up with the semantics of the name as there is no practical win as far as learning how these pure computations benefit us here.

When Knockout has something watching, a computed item is called a subscriber. Thus, it is considered to be a subscriber dependency. If we use the pureComputed method versus the computed method, Knockout will not calculate the value when there are no subscribers. This, of course, adds more speed to our processes by reducing calculations that aren't needed and unnecessary code from running. It is also another way to avoid any chance of memory issues.

When there are no subscribers, a pure computed observable is considered to be sleeping. When there are subscribers it is considered to be listening. The...

Coding documents for computed observables


We have included the following documents about observables just for reference here. While these were available online on the KnockoutJS site, it seemed like a good idea to include them here so you don't have to keep jumping between the website and the book.

A computed observable can be constructed using one of the following forms.

Form 1

The ko.computed( evaluator [, targetObject, options] ) form supports the most common case of creating a computed observable. It has the following attributes:

  • evaluator: This is a function that is used to evaluate the computed observable's current value.

  • targetObject: If given, it defines the value of this whenever Knockout invokes your callback functions.

  • options: This is an object with further properties for the computed observable. See the full list in the following section.

Form 2

The ko.computed( options ) parameter, is a single parameter form for creating a computed observable that accepts a JavaScript object with...

Using a computed observable


A computed observable provides the following functions:

  • dispose(): This manually disposes the computed observable, clearing all subscriptions to dependencies. This function is useful if you want to stop a computed observable from being updated or want to clean up memory for a computed observable that has dependencies on observables that won't be cleaned.

  • extend(extenders): This applies the given extenders to the computed observable.

  • getDependenciesCount(): This returns the current number of dependencies of the computed observable.

  • getSubscriptionsCount(): This returns the current number of subscriptions (either from other computed observables or manual subscriptions) of the computed observable.

  • isActive(): This returns whether the computed observable may be updated in the future. A computed observable is inactive if it has no dependencies.

  • peek(): This returns the current value of the computed observable without creating a dependency.

  • subscribe( callback [,callbackTarget...

Using the computed context


During the execution of a computed observable's evaluator function, you can access ko.computedContext to get information about the current computed property. It provides the following functions:

  • isInitial(): This is a function that returns true if called during the first ever evaluation of the current computed observable, or false otherwise. For pure computed observables, isInitial() is always undefined.

  • getDependenciesCount(): This returns the number of dependencies of the computed observable detected so far during the current evaluation.

    Note

    The ko.computedContext.getDependenciesCount() function is equivalent to calling getDependenciesCount() on the computed observable itself. The reason that it also exists on ko.computedContext is to provide a way of counting the dependencies during the first ever evaluation, before the computed observable has even finished being constructed.

Summary


This chapter opens up a whole load of features and options to make web style coding powerful and elegant. Learning to let a library handle things for you is hard for some but that perspective is ironic as we are programming computers for others to let our work manage things for them. This chapter has added several valuable skills and options to our knowledge and experience:

  • We have learned to integrate data management in Knockout using JSON as an alternate way to pass data in and out.

  • We have seen the incredible power of mapping to make our code another magnitude of elegant using Knockout.

  • We have been introduced to the basics of using AJAX with Knockout.

  • We have learned how to use utility functions for more advanced collection features, and again with less lines of code.

  • Lastly, we learned how to improve the performance of our ViewModel using pure oriented compute functions (with a bonus clip of compute documents from the KnockoutJS online documents).

In our next chapter we will be looking...

lock icon The rest of the chapter is locked
You have been reading a chapter from
KnockoutJS Web Development
Published in: Feb 2015 Publisher: ISBN-13: 9781782161028
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime}