AngularJS Directives : Scopes.

Scopes and their inheritance is something you will frequently be dealing with in AngularJS applications. This is especially true in the context of directives, as they are subject to the scopes they are inserted into and, therefore, require careful management in order to prevent unexpected functionalities. Fortunately, AngularJS directives afford several robust tools that help manage visibility of and interaction with the surrounding scopes.

So, when we create a directive we can specify a scope for it. Scope property can have three values – false(default if not specified), true and {}(isolated):

angular.module("MyModule")  
  .directive("MyDirective", function() {
    return {
      scope: "false|true|{}"
    }
  });

When you set scope:false, the new scope will not be created for this directive. Instead, the directive will use the parent scope by default. So, if you create property in the directive’s scope, you actually create property on the parent scope.

If you have scope:true, you create a new child scope for this directive. This scope will be prototypically inherit from parent scope. This means that you still have access to the parent scope data, but also able to add new properties to a local scope:

angular.module("MyModule")  
  .directive("NewDirective", function() {
    return {
      scope: true,
      link: function(scope, element, attributes) {
        scope.parentObject.someProperty = "I can change it because of inheritance";

        scope.localObject= 
          someProperty: "local prop, only in this direcive."
        }
      }
    }
  });

Ok, now we come to the mostly usable type of scope – Isolated Scope;

angular.module("MyModule")  
  .directive("NewDirective", function() {
    return {
      scope: {
        property: "=",
        expression: "@"
        action: "&"
      },
      link: function(scope, element, attributes) {
        scope.parentObject.someProperty = "I can change it because of inheritance";

        scope.localObject= 
          someProperty: "local prop, only in this direcive."
        }
      }
    }
  });

It calls isolated, because only the properties you specify in object literal will be passed into it. While there are a few instances where we want our directive to be entirely isolated,
more commonly we’ll want to maintain access to a few explicitly specified properties. To do this, Angular provides three symbols for notating what type of access you want to acquire: @, =, and &, which are prepended to the attribute names that you want to derive a value from.

@ – read-only Access

The @ option of scope is a way to pass in a string value, or a value containing {{}}‘s that will get interpolated. This is effectively one way binding.

<div my-isolated-scope-with-name name="{{ customer.name }}"></div>;
angular.module('directivesModule').directive('myIsolatedScopeWithName', function () {
    return {
        scope: {
            name: '@'
        },
        template: 'Name: {{ name }}'
    };
});

The directive code creates an isolate scope that allows a name property to be bound to a value that is passed in from the “outside world”. And if the $scope.customer.name value changes, the directive will automatically pick up the change. However, if the directive changes its name property, the outside value in $scope.customer.name will not change in this case. If you need to keep properties in-sync check out the = local scope property that’s covered next.

= – two-way binding

<div my-isolated-scope-with-model customer="customer"></div>
angular.module('directivesModule').directive('myIsolatedScopeWithModel', function() {
    return {
        scope: {
            customer: '=' //Two-way data binding
        },
        template: '<ul><li ng-repeat="prop in customer">{{ prop }}</li></ul>'
    };
});

The = character tells the directive that the object passed into the customer property should be bound using a two-way binding. If the outside property value changes then the directive’s customer property should automatically be updated. If the directive’s customer property changes then the object in the external scope should automatically be updated.

& – method binding
Sometimes, however, it’s not simply properties that you want to be able to maintain access to. Sometimes you need to be able to call a method on the parent scope. For this, the symbol of choice is &.

The & local scope property allows the consumer of a directive to pass in a function that the directive can invoke. For example, let’s assume you’re writing a directive and as the end user clicks on a button that the directive emits you want to notify the controller. You can’t hard-code the click function to use in the directive since the controller would never know that anything happened. Raising an event could get the job done (using $emit or $broadcast) but the controller would have to know the specific event name to listen for which isn’t optimal either.

A better approach would be to let the consumer of the directive pass in a function that the directive can invoke as it needs. Whenever the directive does useful work (such as detecting when a user clicked on a button) it could then invoke the function that was passed into it. Let’s check an example:

<div some-directive  
   datasource="customer" 
   action="changeData()">
</div>
angular.module('directivesModule').directive('someDirective', function() {
    return {
        scope: {
            datasource: '=',
            action: '&'
        },
        template: '<ul><li ng-repeat="prop in datasource">{{ prop }}</li></ul> ' +
            '<button ng-click="action()">Change Data</button>'
    };
});

The directive creates a custom local scope property within its isolate scope named action. This is done using scope { action: ‘&’ }. In this example action is really just an alias for click. When action is invoked the click function that was passed in will be called. Notice that the following code from the directive’s template refers to the action local scope property and invokes it (since it’s simply a reference to a function) as the button is clicked. This delegates control to whatever function was passed to action.

Conclusion

  • @ Used to pass a string value into the directive
  • = Used to create a two-way binding to an object that is passed into the directive
  • & Allows an external function to be passed into the directive and invoked

http://jonathancreamer.com/working-with-all-the-different-kinds-of-scopes-in-angular/

Share this post:Tweet about this on TwitterShare on Facebook0Share on LinkedIn0Share on Google+0Share on Reddit0Email this to someoneDigg this