Saturday, June 21, 2014

AngularJs Communicate Between Directives and Controllers


Recently in one of my project we were using AngularJs and created a directive for timepicker where user can enter timer in hh:mm AM/PM format. Now on one of the HTML form we have a button. When the button is clicked we have to disable the input for the timepicker. For that we have to access scope of directive from scope of AngularJs controller so that se can disable the respective field. In this blog I am going to explain how to do this.

AngularJs allows you to create directives with isolated scope which has some binding to parent scope. Bindings are defined by specifying attributes in HTML.  In some cases it may not be good as it's hard to synchronize both the scopes. So ideally parent and directive scope should be maintained separately. Better way to communicate between directives and controllers is through directive attributes. Let's see and example.  I have defined my HTML as follow for my timepicker directive.

<timepicker is-not-open="notOpen" hour-step="1" minute-step="30" show-meridian="true"></timepicker>

As you can see above is-not-open is the attribute defined for directive and it is bind to notOpen variable in my controller.

$scope.notOpen = false;

Now lets see how to mention attribute in directive scope.

angular.module('ui.bootstrap.timepicker', [])
.directive('timepicker', ['timepickerConfig', function (timepickerConfig) {
  return {
    restrict: 'EA',
    replace: true,
    scope: { isNotOpen: "=" },
    templateUrl: 'template/timepicker/timepicker.html',
    link: function(scope, element, attrs, ngModel) {

As you can see in above code we have defined attribute with scope: { isNotOpen: "=" }. Now you can define a function to watch this variable in directives. For example there is a method in parent controller which sets notOpen variable to true.

$scope.setNotOpenStatus = function(){
      $scope.notOpen = true;

Once it is set here, the directive is notified about the change and as I mentioned you can keep watch on the attribute.

scope.$watch('isNotOpen', function (newValue, oldValue) {
          if(newValue == true){
              //do something

Same way you can have watch function in parent controller which would be notified if attribute value is changed inside directive.

Hope this helps you.

No comments:

Post a Comment