Monday, 29 January 2018

PreLink, PostLink and Controller Methods of Angular Directives

PreLink, PostLink and Controller Methods of Angular Directives

Link function of an Angular Directive
As the name implicates, the link function has the duty of linking the model to the templates. Link function is the place where AngularJs does the data binding to the compiled templates. Let’s take a look at the signature of a link function.

link: function LinkFn(scope, elem, attr, ctrl){}

There are 4 parameters available to the link function.

scope : The scope of the directive
elem : Dom element where the directive is applied
attr : Collection of attributes of the Dom Element
ctrl : Array of controllers required by the directive

Now let’s create a simple directive to see how the data binding works.

var app = angular.module('app', []);
app.directive('dad', function () {
    return {
        restrict: 'EA',
        template: '<div>{{greeting}}{{name}}</div>',
        link: function(scope,elem,attr){
            scope.name = 'Paul';
            scope.greeting = 'Hey, I am ';
        }
    };
});

<div ng-app="app">
    <dad></dad>
</div>

The name and greeting properties attached to the scope are linked to the template once the link function is executed. And, the browser will show “Hey, I am Paul” in the view.

The above is the usual way to create a link function inside a directive. However, AngularJs allows to set the link property to an object also. Advantage of having an object is, we can split the link function into two separate methods called, pre-link and post-link.

Both Pre & Post link functions have the same syntax as defined below but the only difference is the order in which they get executed.

Pre-linking 
function Executed before the child elements are linked. Not safe to do DOM transformation since the compiler linking function will fail to locate the correct elements for linking.

Post-linking function Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.

Lets start by defining a simple directive

var mod = angular.module('Mod', []);
           mod.directive('myDir', function () {
               return {
                   restrict: 'E',
                   controller: function ($scope, $element) {
                       console.log(': controller');
                       console.log($element.html());
                   },
                   compile: function (tElem, tAttrs) {
                       console.log(': compile');
                       console.log(tElem.html());
                       return {
                           pre: function (scope, iElem, iAttrs) {
                               console.log(': pre link');
                               console.log(iElem.html());
                           },
                           post: function (scope, iElem, iAttrs) {
                               console.log(': post link');
                               console.log(iElem.html());
                           }
                       }
                   }
               }
           });


Let’s use it in our html code like this

<my-dir>
     Parent
     <my-dir>Child</my-dir>
</my-dir>

Above we have defined a very simple directive using all important functions of a directive. We have nested that directly in itself and added parent/child text in the template. Now if we see the output we know the order in which these directives get executed.

: compile
Parent
<my-dir>Child</my-dir>
: compile
Child
: controller
Parent
<my-dir>Child</my-dir>
: pre link
Parent
<my-dir>Child</my-dir>
: controller
Child
: pre link
Child
: post link
Child
: post link
Parent
<my-dir>Child</my-dir>

Looking at the above we can see the order in which these functions execute. This order is always very important, the reason we will see later.

So to conclude the order is:
Compile Parent -> Compile Child -> Controller Parent -> PreLink Parent -> Controller Child -> PreLink Child -> Post Link Child -> Post Link Parent


Continue Reading →

AngularJS –Access Scope from outside function ($apply)

We know angularjs has a data binding between scope and html, which means what ever data changes we make in our controller scope it gets reflected to our html. But things change when we use a 3rd party library or external events to make changes to our scope.

Lets take an example to see how this happens

HTML
<body ng-app='MainApp'>
    <div ng-controller='MainCtrl'>
      <div>
        <div>{{text}}</div>
        <button id='click_button' type='button' >Click Me</button>
        <p>When You Click, only alert shows but text doesn't update</p>
      </div>
    </div>
</body>

ANGULARJS
var mainMod = angular.module('MainApp', []);
mainMod.controller('MainCtrl', ['$scope',
    function ($scope) {
         
         $scope.text = 'Hey';
         $('#click_button').click(function(){
           alert('Click!');
           $scope.text = new Date();
         });
    }
]);

In the above, code I have taken a simple scope variable “text” and used jquery library to demonstrate an outside function. So using jquery’s click function, when you click on the “Click Me” button i have changed the scope “text” variable to current date. If you run the code you will see that it will not work.

Access Angular Scope From Outside Function or 3rd Party Library
AngularJS exposes a method “$apply” for this purpose. This function is used to inform angular that changes have been made to $scope variable from an outside function or event.

Here is code for the same

ANGULARJS
var mainMod = angular.module('MainApp', []);
mainMod.controller('MainCtrl', ['$scope',
    function ($scope) {
         
         $scope.text = 'Hey';
         $('#click_button').click(function(){
           alert('Click!');
           $scope.$apply(function(){
             $scope.text = new Date();
           });
         });
    }
]);

Now we see Date gets updated on button click.
The only change made to above code was

$scope.$apply(function(){
  $scope.text = new Date();
});

So we made the $scope changes inside the $apply function. This tell answer to run the $digest cycle to check for any changes in $scope.

Difference Between $apply and $apply(fn)

There are two ways to use the $apply function, taking the above example

 Method1:

$scope.$apply(function(){
             $scope.text = new Date();
           });

Method2:

$scope.text = new Date();
$scope.$apply();

In most cases both the above will give you the same desired effect, but there are difference between the two. As per angular documentation, pseduo code for $apply is

function $apply(expr) {
  try {
    return $eval(expr);
  } catch (e) {
    $exceptionHandler(e);
  } finally {
    $root.$digest();
  }
}

So the Method1 takes care of exception handling and always run the digest cycle. So method1 is always preferred to method2.

   
Continue Reading →

Topics

ADFS (1) ADO .Net (1) Ajax (1) Angular (47) Angular Js (15) ASP .Net (14) Authentication (4) Azure (3) Breeze.js (1) C# (55) CD (1) CI (2) CloudComputing (2) Coding (10) CQRS (1) CSS (2) Design_Pattern (7) DevOps (4) DI (3) Dotnet (10) DotnetCore (20) Entity Framework (5) ExpressJS (4) Html (4) IIS (1) Javascript (17) Jquery (8) jwtToken (4) Lamda (3) Linq (10) microservice (4) Mongodb (1) MVC (46) NodeJS (8) React (10) SDLC (1) Sql Server (32) SSIS (3) SSO (1) TypeScript (3) UI (1) UnitTest (2) WCF (14) Web Api (16) Web Service (1) XMl (1)

Dotnet Guru Archives