Playing with Scope Inheritance In Angular

In my previous blog I have discussed about the prototypical inheritance in Javascript, In AngularJS, a child scope normally prototypical inherits from its parent scope.Today while working with angular I found a interesting concept regarding prototypical inheritance in angular. Now lets directly start with an example,

Here is the PLUNK.

In the above example We have created an array “Skills” which contains a set of skills, and a model “mySkill” to store a particular skill in $scope. We are using the “Skills” array to populate our check boxes and ‘mySkill’ model to store the skill selected by the user.Finally we are showing the skill selected by the user. But this will not work the way we are  expecting.

It will not update our model ‘mySkill’ according to the checkbox selected by the user. This looks like a strange issue. Now the question is why Its not updating our model properly? This is because ng-repeat creates a new child scope which is prototypically inherited from parent scope and the child scope gets its own property(‘mySkill’) that hides/shadows the parent property of the same name, But does not update the parent scope ‘mySkill’ property. This is not something AngularJS is doing – this is how JavaScript prototypical inheritance works.  Directives like ng-repeat, ng-view and ng-include create new child scope where this kind of problem occurs.

This issue with primitives can be easily avoided by following the best practice of always have a ‘.’ in ng-models.Having a ‘.’ in models will ensure that prototypical inheritance is in play. So, we should use

<input type="text" ng-model="someObj.prop1"> rather than 
<input type="text" ng-model="prop1">.

If you really want/need to use a primitive, then we can use $parent.parentScopeProperty in the child scope which will prevent the child scope from creating its own scope.

<input type="text" ng-model="$parent.prop1">

Now to make our example work properly we can modify it as below,

Here is the PLUNK.

So what exactly we did is we have modified  $scope.mySkill = “Java” to $scope.mySkill = {fav: “Java”} and used mySkill.fav as our model. So now inside ng-repeat It will not create a duplicate mySkill property in the child scope instead it will update the parent scope mySkill.fav property and everything will work as expected.

This is one of the “Best Practices” in Angular JS.

Summary:

If we use a primitive type (as ‘mySkill’ in 1st example) as model for data binding, essentially ng-repeat will create a new child scope property with the same name . Changing the child scope property’s value (i.e., using ng-model, hence child scope property mySkill) does not change the  parent scope mySkill property. So in my first example above, each child scope gets a mySkill property that is independent of the mySkill property defined in the controller or the parent scope. But if we will use a Object type , It will use prototypical inheritance and always update the property on the parent scope.

Advertisements

Custom Validation In Angular Js

Angular JS having very strong support for form validation. It’s having builtin $error object,predefined CSS classes and patterns that makes the form validation much easier. Still there are plenty of cases where we can not use angularjs default validation.Its off course not possible to cover all the cases.

So we can write up our own custom directives for adding custom validation to our application.What we really want to do is to build a directive that will require ngModel(require: ‘ngModel’). Requiring ngModel will pass the ngModelController into the linking function as the fourth argument. The ngModel controller has a lot of handy functions on it, in particular there is $setValidity, which allows us to set the state of a model field has $valid or $invalid as well as set an $error flag.
The ng-model directive provides two arrays of functions to which the custom validation logic can be hooked:i.e

  1. $parsers
  2. $formatters

Usage of both of these arrays looks similar, but they are invoked under different conditions.

$parsers:

Array of functions to execute, as a pipeline, whenever the control reads value from the DOM. Each function is called,
in turn, passing the value through to the next. The last return value is used to populate the model. Used to sanitize /convert the value as well as validation. For validation, the parsers should update the validity state using $setValidity(), and return undefined for invalid values.

In most of the cases, $parsers is the right option to handle the logic of custom validation. Functions added to $parsers are called as soon as the value in the form input is modified by the user.

$formatters:

Array of functions to execute, as a pipeline, whenever the model value changes. Each function is called, in turn, passing the value through to the next. Used to format / convert values for display in the control and validation.
Formatters are invoked when the model is modified in the code. They are not invoked if the value is modified in the textbox. $formatters are useful when there is a possibility of the value getting modified from the code.

Example:

Suppose we want to validate our username. It must be alphanumeric only.

Though we can achieve the same kind of validation easily using ng-pattern, I have shown this example just for the demo purpose to show how $parser and $formatter works. Here is the PLUNK.

How Two Way Data Binding works in Angular JS

Two way data binding is one of the most powerful feature in Angular JS.It will help you to save from writing a lots of regular code.

What does it mean by two-way data binding?

In simple words, two way data binding means AngularJs synchronizes the data between the scope model and veiw.
It means if a value of a scope model changes it automatically updates the same value in the view and similarly if the value in the view changes it automaticaly updates the value in the scope model.

How does two way data binding works in Angular JS?

two wayWhen we write an expression ({{dyanvar}}), behind the scenes Angular sets up a watcher on the scope model, which in turn updates the view whenever the model changes. This watcher is like any other watcher we set up in AngularJS:

$scope.$watch('dyanvar', function(newValue, oldValue) {
  //update the view with newValue
});

The second argument passed to $watch() is known as a listener function, and It is called whenever the value of dyanvar changes.

When the value of dyanvar changes this listener is called, updating the expression in HTML.
But still,How does Angular figure out when to call this listener function? In other words, how does AngularJS know when {{dyanvar}} changes so that it can call the corresponding listener? Does it run a function in a particular interval to check whether the value of the scope model has changed or not ? Well, this is where the $digest cycle comes into the picture.

It’s the $digest cycle where the watchers are fired. When a watcher is fired, AngularJS evaluates the scope model, and if it has changed its value then the corresponding listener function is called. So, Now the question is when and how this $digest cycle starts.

The $digest cycle starts as a result of a call to $scope.$digest(). Assume that we change a scope model in a handler function through the ng-click directive. In that case AngularJS automatically triggers a $digest cycle by calling $digest(). When the $digest cycle starts, it fires each of the watchers. These watchers check if the current value of the scope model is different from last calculated value. If yes, then the corresponding listener function executes. As a result, if you have any expressions in the view they will be updated. In addition to ng-click, there are several other built-in directives/services that let us change models (e.g. ng-model, $timeout, etc) and automatically trigger a $digest cycle.

But Angular doesn’t directly call $digest(). Instead, it calls $scope.$apply(), which in turn calls $rootScope.$digest().
As a result of this, a digest cycle starts at the $rootScope, and subsequently visits all the child scopes calling the watchers along the way.

Now, let’s assume you attach an ng-click directive to a button and pass a function name to it. When the button is clicked,AngularJS wraps the function call within $scope.$apply(). So, your function executes as usual, change models (if any), and a $digest cycle starts to ensure your changes are reflected in the view.

When do we need to use $apply() manually?

If AngularJS usually wraps our code in $apply() and starts a $digest cycle, then when do you need to do call $apply() manually?
Actually, AngularJS makes one thing pretty clear. It will account for only those model changes which are done inside AngularJS’ context Angular’s built-in directives already do this so that any model changes you make are reflected in the view.
However, if you change any model outside of the Angular context,(For example if we update a model using a jquery plugin) then you need to inform Angular of the changes by calling $apply() manually. In these cases either we can call to $apply() or $digest() to kick of a digest cycle for dirty checking , but its always recommended to use $apply() as it has built in error handling mechanism.