Tuesday, 12 April 2016

events,scope,controllers : Advance Beginner I

Events, Scope and Controllers play very important role to make a directive interactive as well as to encapsulate data.Without wasting time lets begin by adding a functionality to our existing code, refer First Directive if you have not read my previous blog.
Lets put a button to call Avengers.So whenever user is in danger he can click this button to call Avengers for help.See while coding you can do anything in the world you want!
First we will add bootstrap as we will be using them to give some styling.Next we add a button in displayInfo.html

<button class="btn btn-primary" ng-click="callAvengers(user)"
 ng-show="!user.message">Call Avengers<button>

I have added ng-show here so that user can click button only once.Once user gets the message from Avengers,button disappears.
I have added ng-click directive to trigger a function on click of this button.Now where should we put this function? Lets put it in our controllers as the scope of mainCtrl is visible to directive.

$scope.callAvengers = function(user) {
    user.message = "hey buddy,Avengers will be here shortly!"
  }

Now lets review the code
I have done few styling using Bootstrap and then just added a button and function inside mainCtrl as mentioned above.But have you guys noticed that we have a major problem here? Call Avengers button lives inside directive but the method that handles it is placed inside the controller.It doesn't follow data encapsulation.
The solution is ver simple.We provide separate controller for the directive.We do this by adding a property called controller in the directive as following.

angular.module('myApp').directive('displayInfo', function() {
  return {
    templateUrl: "displayInfo.html",
    restrict: "E",
    controller: function($scope) {
      $scope.callAvengers = function(user) {
        user.message = "hey buddy,Avengers will be here shortly!"
      }
    }
  }
});


As you see by adding a controller to a directive we are also injecting scope just as a normal controller does.So what is the difference between two scopes?Well that depends on how you set your relationship between the two scopes.There are three ways you can set relationship between these two scopes.By default  directive has shared scope with the controller which contains the directive as shown below.

Directive with shared scope


Here inside parent scope i.e mainCtrl both our user object and directive lies and hence directive can access the objects in parent scope.

Directive with inherited scope


Here child scope is created which inherit the properties of parent scope.So objects on parent's scope is visible to child scope but parent scope can't see object in child scope. We can create inherited scope simply by adding a property scope inside directive and set its value to true.

angular.module('myApp').directive('displayInfo', function() {
  return {
    templateUrl: "displayInfo.html",
    restrict: "E",
    scope: true,
    controller: function($scope) {
      $scope.callAvengers = function(user) {
        user.message = "hey buddy,Avengers will be here shortly!"
      }
    }
  }
});

If we set scope value as false it will share scope with parent.

Directive with isolated scope


Here the controller(which contains the directive) and directive has different scope and neither of them can access object other than their own scope. But sometime we want our directive to access its parent's scope.In isolated scope we can do object to object binding between scopes.
If we replace value of scope from true to an object, we create a isolated scope.Inside that object we specify parent object which we want to be accessible from child scope followed by string=
For example,
scope: {
    user:'='
}
This tell directive to expect an object named user.
Still now I have to specify what on parent scope will be my user object in child scope.I can do that by adding an attribute in the element <display-info user='DCUser'>


This solves the problem that I asked in my previous blog about displaying different data with same directive in same page.
We have seen how directive can receive parameter.Here displayInfo directive receives parameter which is an object.Directives can also receive parameter as a simple value parameter(strings) and as a function.I will explain that in my next blog. I want you guys to think about something.Can we use another directive say directive as an attribute inside our displayInfo directive?Hope its going easy for you guys to understand directives.If you have any problem you can mail me.Happy coding :)

1 comment: