This post is all about understanding the working mechanism of an AngularJS application. 2-way data binding is the core of AngularJS which creates the magic that you see in most of its application.we will learn how it works.
INTRODUCTION TO ANGULARJS
AngularJS is an one of the most popular client side framework and developed by Google Inc.This framework is based on the MVW design pattern.The details about MVW is listed below.
- M: It stands for Model and represents the real data object.
- V: It stands for View and represents the how it look to the end user.For a web application it is the HTML DOM(Document Object Model) which is rendered by the browser.
- W: it is a paraphrase "What Ever". This component is responsible in establishing the relationship between Model and View.
We will find many great and impressive web application built on the AngularJS library.All of these application are single page in architecture.
WHAT IS SINGLE PAGE APPLICATION?
You can find many web application where contents/pages loads dynamically without reloading the entire application.In the early years of web 2.0 it was achieved using AJAX(XMLHTTPRequest) where client makes a call to the server using XMLHTTPRequest protocol and then server process the request and send the targeted response to the client for rendering.All the application logic are handled by the sever and the client's only responsibility is to initiate requests.These applications became more server extensive and hence there are many performance and cost parameters gets involved which creates the problem both from development and maintenance area.With the advent of new technologies like HTML5 and supports from the most of the common browsers a new architecture called Single Page Application(SPA) is came for rescue.In a Single Page Application the whole presentation logic present in the client side.In an SPA based application the main components are router,controller,template,real-time communication and local storage.
AngularJS library provides different built-in modules and exposed as library methods to the web developer to build a single page web application.Below code shows the syntax of creating these SPA components in AngularJS library.
angular.module("module name",function(){}); angular.controller("controller name",function(){}); angular.config(function($routeProvider, $locationProvider) { $routeProvider.when('routing path', { templateUrl: 'HTML template file', controller: 'Controller name' }); });
HOW ANGULARJS APPLICATION LOADS?
AngularJS application gets initialized when DOMContentLoaded
events gets fired.A DOMContentLoded event is fired on the document when all the HTML elements are loaded and parsed.It does not wait for all the resources like images,styles and other to be downloaded to browser.Once this event is fired Angular executes the below steps.
- Angular looks for ngApp directives in the DOM tree. ngApp works like a marker to AngularJS, which tells the AngularJS that the portion of HTML markup needs compilation.
- If Angular finds multiple ngApp directives then it takes the 1st ngApp covered HTML portion and starts the process of auto-bootstrapping.In auto-bootstrapping all other depended modules and injectors gets loaded to the AngularJS application.
- The other remaining ngApp directives needs manual bootstrapping.A manual bootstrapping can be done using angular.bootstrap() method.
Once the ngApp root is determined the compilation process of HTML markup gets triggered by considering the ngApp element as the root of the application.During the compilation process it loads all the dependencies like injector or modules.
WHAT IS 2 WAY DATA BINDING?
Each and every AngularJS application is cooked by the two ingredients a <Model, View> and a secret sauce.This secret sauce is the relationship between model and view termed as 2-way data binding mechanism.In this mechanism when Model /View gets updated then View/Model gets updates automatically without any reload of pages.
In AngularJS this 2-way data binding is made possible by the help of scope.Each Model and view is under a scope object.Due to this scope object the changes are in sync between Model and View.Let's discuss more about scope in the next section.
SCOPE OBJECT
Scope object is simply a plain old JavaScript object . It provides the execution context where Model and View lives and get evaluated based on the given expression.AngularJS provides 2 types of scope objects global and local scope.These scope objects are listed below.
- $rootScope: This object provides the application level scope and hence any properties defined inside this context is global and accessible throughout the application.
- $scope: This object provides local scope and hence any properties defined inside this context is not accessible beyond that scope.
AngularJS also support two more useful features that really helps in developing the application.The details of these features are listed below.
- Nested Scope: Scope object can be nested.A child scope can access the properties of parent scope.This is made possible by JavaScript prototypal inheritance.
- Isolated Scope: This type of scope object does not participate in protypal inheritance instead they create their own private scope.
DIGEST CYCLE
Digest cycle is the center of an AngularJS application.Using digest cycle AngularJS keeps the model and view in sync.A digest cycle run by AngularJS application by calling $digest()
method.
In JavaScript when an event is fired, an event object is created and a callback function gets executed with this event object. This callback method then runs inside the JavaScript function and returns to the browser for the DOM update.A digest cycle is like callback function which is get triggered by AngularJS application.
ANGULARJS STATE
The digest cycle creates this magic of 2-way data binding is using different states for the scope variables.There are many different states a scope variable can have.But digest cycle only uses dirty and pristine state.The details of these states are listed below.
- Dirty State:When users interact with the models of the scope these models changed their state to dirty state. If you inspect the HTML elements through a developer tool you can find that a new class call ng-dirty has been get attached to the element’s class.
- Pristine State:The state of the model when it is untouched or after the digest cycle completed is called pristine state. If you inspect the HTML elements through a developer tool you can find that a new class called ng-pristine has been get attached to the element’s class.
The process of digest cycle is also known as dirty checking. Where the system collects all the objects which have dirty bit set to true and do the defined process to make the object to pristine state.
ANGULAR WATCH METHOD
AngularJS $scope object provides $watch() method for watching the changes to the scope variables.Each watch callback method gets called with a digest cycle.As the digest cycle is responsible to create a sync between model and view.
The syntax of this method is listed below.
$scope.$watch("property name",function(newValue,oldValue){ //callback function });
The $watch() method takes 2 parameters and details of them are listed below.
- property name : This parameter represent the scope variable name in string format which needs to be watched.
- callback function : This parameter is of type function and act as a listener function which gets triggered when there is a change in scope variable.
The latest AngularJS version has 3 different types of watcher method.The details of these watcher methods are listed below.
- $watch: This method is for watching single scope variable.
- $watchCollection:This method is for watching a scope variable of type array.
- $watchGroup: This method is for watching a group of scope variables.
ANGULAR APPLY METHOD
When an scope variable gets updated from outside Angular context then AngularJS can not detect the change which results in inconsistency between model and view.In this type of scenario $apply() method come in handy.$apply method is defined inside the scope object.So if we are writing any code outside of AngularJS then it must be wrapped around the $apply method to get a proper sync between model and view.
$apply method achieve this magic by simply calling the $digest method after the block code execution.In simple words $apply() method is upper level of wrapper around $digest.The syntax of $apply method is listed below.
$scope.$apply(function(){ //your code goes here });
EXAMPLE
Let’s checkout a simple example which demonstrate the AngularJS 2-way data binding.Below code has 3 examples.In the 1st example it shows the use of $watch method for a single scope variable.2nd example show the use of $watchCollection method and the 3rd example shows the $watchGroup method.In all of this example you can find a similarity where users input get synched up in among model and view.
<!DOCTYPE html> <html ng-app="myApplication"> <head> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.19/angular.min.js"></script> <meta charset="utf-8"> <title>$watch-collection-Group Service</title> </head> <body ng-controller="MyController"> <h1>$watch Example</h1> <h5>String : {{aString}}</h5> <h5>Length of String: {{leghthString}}</h5> <button ng-click="addS()">+S</button> <br/> <br/> <hr> <h1>$watchCollection Example</h1> <h5>Array Collection: {{stringArray}}</h5> <h5>Length of Array: {{stringArrayLength}}</h5> <input type="text" ng-model="newString" placeholder="Enter a string"> <button ng-click="pushString()">push</button> <br/> <br/> <hr> <h1>$watchGroup Example</h1> <h5>Number 1: {{number1}}{{typeOfNumber1}}</h5> <h5>Number 2: {{number2}}{{typeOfNumber2}}</h5> <h5>Number 3: {{number3}}{{typeOfNumber3}}</h5> <button ng-click="addOneAll()">+1 All</button> <script> var myApplication = angular.module("myApplication", []); myApplication.controller("MyController", function($scope) { $scope.aString = "S"; $scope.addS = function() { $scope.aString += "S"; }; $scope.$watch("aString", function(newValue, oldValue) { $scope.leghthString = newValue.length; }); $scope.stringArray = ["X", "Y"]; $scope.pushString = function() { $scope.stringArray.push($scope.newString); }; $scope.$watchCollection("stringArray", function(newValue, oldValue) { $scope.stringArrayLength = $scope.stringArray.length; }); $scope.number1 = 9; $scope.number2 = 22; $scope.number3 = 112; $scope.addOneAll = function() { $scope.number1++; $scope.number2++; $scope.number3++; }; $scope.$watchGroup(['number1', 'number2', 'number3'], function(newValues, oldValues) { $scope.typeOfNumber1 = newValues[0] % 2 === 0 ? "Even" : "odd"; $scope.typeOfNumber2 = newValues[1] % 2 === 0 ? "Even" : "odd"; $scope.typeOfNumber3 = newValues[2] % 2 === 0 ? "Even" : "odd"; }); }); </script> </body> </html>
OUTPUT
Below embedded JSBIN shows the output of the above code.
JS Bin on jsbin.com
SUMMARY
From this discussion we have learned How 2-way data binding is implemented in AngularJS which makes this framework so popular.