Wednesday, March 1, 2017

KnockoutJS - Observables

KnockoutJS is build upon 3 important concepts. Those are:
  • Observables and dependency tracking between them - DOM elements are connected to ViewModel via 'data-bind'. These 2 exchange information through Observables. This automatically takes care of dependency tracking.
  • Declarative Bindings between UI and ViewModel - DOM elements are connected to ViewModel via 'data-bind' concept.
  • Templating to create re-usable components - Templating provides robust way to create complex web applications.
We will study Observables in this chapter.
As the name specifies, when you declare a ViewModel data/property as Observable, any modification done every time to that data is automatically reflected to all places wherever it is used. This also includes refreshing related dependencies. KO takes care of these things and we don't have to write any extra code to achieve this.
Using Observable it becomes very easy to make UI and ViewModel communicate dynamically.

Syntax

You just need to declare ViewModel property with function ko.observable() to make it Observable.
this.property = ko.observable('value');

Example

Let's try below example which demonstrates use of Observable:
<!DOCTYPE html>
<head>
<title>KnockoutJS Observable Example</title>
<script src="https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" type="text/javascript"></script>
</head>
<body>
   <!-- This is called "view" of HTML markup that defines the appearance of UI -->

   <p>Enter your name: <input data-bind="value: yourName" /></p>
   <p>Hi <strong data-bind="text: yourName"></strong> Good Morning!!!</p>

   <script>
   <!-- This is called "viewmodel". This javascript section defines the data and behavior of UI -->

   function AppViewModel() {
       this.yourName = ko.observable("");
   }

   // Activates knockout.js
   ko.applyBindings(new AppViewModel());
   </script>
</body>
</html>
  • <p>Enter your name: <input data-bind="value: yourName" /> <p>
    This line is for input box. As you see, we have used data-bind attribute to bind yourName value to ViewModel.
  • <p>Hi <strong data-bind="text: yourName"></strong> Good Morning!!!</p>
    This line just prints value of yourName. Note that here data-bind type is text as we are simply reading value.
  • this.yourName = ko.observable("");
    ko.observable keeps an eye on yourName variable for any modification in data, once it happens then corresponding places also get updated with changed value. When you run above code, an input box will appear. As and when you update that input box, its new value get reflected or refreshed in places wherever it is used.

Output

Let's carry out the following steps to see how above code works:
  • Save above code in first_observable_pgm.htm file.
  • Open this HTML file in a browser.
  • Enter name as Scott and see that name is reflected in output.
Data modification can take place either from UI or from ViewModel. Irrespective of from where data is changed, UI and ViewModel keep synchronization among them. This makes it two-way-binding mechanism. In above example when you change your name in input box, ViewModel gets new value. When you change yourName property from inside of ViewModel then UI receives new value.

Reading and writing Observables

Table below lists read and write operations which can be performed on Observables.
S.N.Read/Write Operation & Syntax
1 Read
To read value just call Observable property without parameters like:
 AppViewModel.yourName();
2 Write
To write/update value in Observable property, just pass the desired value in parameter like:
 AppViewModel.yourName('Bob');
3 Write multiple
Multiple ViewModel properties can be updated in a single row with the help of chaining-syntax like:
 AppViewModel.yourName('Bob').yourAge(45);

Observable Arrays

Observable declaration takes care of data-modifications of single object. ObservableArray works with collection of objects. This is very useful feature when you are dealing with complex applications containing multiple type of values and changing their status frequently based on user actions.

Syntax

this.arrayName = ko.observableArray();    // It's an empty array
Observable array only tracks which objects in it are added or removed. It does not notify if individual object's properties are modified.

Initialize it for first time

You can initialize your array at the same time you declare it as Observable by passing initial values to constructor as below:
this.arrayName = ko.observableArray(['scott','jack']);

Reading from Observable Array

You can access Observable array elements as below:
alert('The second element is ' + arrayName()[1]);

ObservableArray Functions

KnockoutJS has got its own set of Observable array functions. Those are convenient because:
  • These functions works on all browsers.
  • These functions will take care of dependency tracking automatically.
  • Syntax is easy to use. For example to insert an element into array you just need to use arrayName.push('value') instead of arrayName().push('value').
Below is the list of various Observable Array methods.
S.N.Methods & Description
1 push('value')
Inserts a new item at the end of array.
2 pop()
Removes the last item from the array and returns it.
3 unshift('value')
Inserts a new value at the beginning of the array.
4 shift()
Removes the first item from the array and returns it.
5 reverse()
Reverses order of the array.
6 sort()
Sorts array items in ascending order.
7 splice(start-index,end-index)
Accepts 2 parameters start-index and end-index, removes items starting from start to end index and return them as an array.
8 indexOf('value')
This function returns index of first occurrence of parameter provided.
9 slice(start-index,end-index)
This method slices out a piece of an array. Returns items from start-index up to end-index.
10 removeAll()
Removes all items and return them as array.
11 remove('value')
Remove items matching with parameter and return as array.
12 remove(function(item) { condition })
Removes items which are satisfying condition and return them as array.
13 remove([set of values])
Remove items which are matching with given set of values.
14 destroyAll()
Marks all items in array with property _destroy with value true.
15 destroy('value')
Search for item equal to parameter and mark it with a special property _destroy with value true.
16 destroy(function(item) { condition})
Finds all items which are satisfying condition, mark them with property _destroy with true value.
17 destroy([set of values])
Finds items which are matching with given set of values, mark them as _destroy with true value.
Note: Destroy and DestroyAll Functions From ObservableArrays are mostly for 'Ruby on Rails' developers only.
When you use destroy method, the corresponding items are not really deleted from array at that moment but are made hidden by marking them with property _destroy with true value so that they can't be read by UI. Items marked as _destroy equal to true are deleted later while dealing with JSON object graph.

No comments:

Post a Comment