Angular directive scope attribute

In AngularJS, Scope works as a glue between controller and model. While working with directive you can use scope attribute and it can be true, false or an object.

While creating custom directives you can use scope in 3 different manners as explained below:

  • false (default): The directive will use its parent’s scope. No scope will be created for the directive.
  • true: A new child scope that prototypically inherits from its parent will be created for the directive’s element. If multiple directives on the same element request a new scope, only one new scope is created.
  • {...} (an object): A new “isolate” scope is created for the directive’s template. The ‘isolate’ scope differs from normal scope in that it does not prototypically inherit from its parent scope. This is useful when creating reusable components, which should not accidentally read or modify data in the parent scope. Note that an isolate scope directive without a template or templateUrl will not apply the isolate scope to its children elements.

The ‘isolate’ scope object hash defines a set of local scope properties derived from attributes on the directive’s element. These local properties are useful for aliasing values for templates. The keys in the object hash map to the name of the property on the isolate scope; the values define how the property is bound to the parent scope, via matching attributes on the directive’s element:

  • @ or @attr – bind a local scope property to the value of DOM attribute. The result is always a string since DOM attributes are strings. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <my-component my-attr="hello {{name}}"> and the isolate scope definition scope: { localName:'@myAttr' }, the directive’s scope property localName will reflect the interpolated value of hello {{name}}. As the name attribute changes so will the localName property on the directive’s scope. The name is read from the parent scope (not the directive’s scope).
  • = or =attr – set up a bidirectional binding between a local scope property and an expression passed via the attribute attr. The expression is evaluated in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <my-component my-attr="parentModel"> and the isolate scope definition scope: { localModel: '=myAttr' }, the property localModel on the directive’s scope will reflect the value of parentModel on the parent scope. Changes to parentModel will be reflected in localModel and vice versa. If the binding expression is non-assignable, or if the attribute isn’t optional and doesn’t exist, an exception ($compile:nonassign) will be thrown upon discovering changes to the local value, since it will be impossible to sync them back to the parent scope.By default, the $watch method is used for tracking changes, and the equality check is based on object identity. However, if an object literal or an array literal is passed as the binding expression, the equality check is done by value (using the angular.equals function). It’s also possible to watch the evaluated value shallowly with $watchCollection: use =* or =*attr
  • < or <attr – set up a one-way (one-directional) binding between a local scope property and an expression passed via the attribute attr. The expression is evaluated in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name.For example, given <my-component my-attr="parentModel"> and directive definition of scope: { localModel:'<myAttr' }, then the isolated scope property localModel will reflect the value of parentModel on the parent scope. Any changes to parentModel will be reflected in localModel, but changes in localModel will not reflect in parentModel. There are however two caveats:
    1. one-way binding does not copy the value from the parent to the isolate scope, it simply sets the same value. That means if your bound value is an object, changes to its properties in the isolated scope will be reflected in the parent scope (because both reference the same object).
    2. one-way binding watches changes to the identity of the parent value. That means the $watch on the parent value only fires if the reference to the value has changed. In most cases, this should not be of concern, but can be important to know if you one-way bind to an object, and then replace that object in the isolated scope. If you now change a property of the object in your parent scope, the change will not be propagated to the isolated scope, because the identity of the object on the parent scope has not changed. Instead you must assign a new object.

    One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings back to the parent. However, it does not make this completely impossible.

  • & or &attr – provides a way to execute an expression in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <my-component my-attr="count = count + value"> and the isolate scope definition scope: { localFn:'&myAttr' }, the isolate scope property localFn will point to a function wrapper for the count = count + value expression. Often it’s desirable to pass data from the isolated scope via an expression to the parent scope. This can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression is increment(amount) then we can specify the amount value by calling the localFn as localFn({amount: 22}).

All 4 kinds of bindings (@=<, and &) can be made optional by adding ? to the expression. The marker must come after the mode and before the attribute name. See the Invalid Isolate Scope Definition error for definition examples. This is useful to refine the interface directives provide. One subtle difference between optional and non-optional happens when the binding attribute is not set:

  • the binding is optional: the property will not be defined
  • the binding is not optional: the property is defined

Combining directives with different scope definitions

In general it’s possible to apply more than one directive to one element, but there might be limitations depending on the type of scope required by the directives. The following points will help explain these limitations. For simplicity only two directives are taken into account, but it is also applicable for several directives:

  • no scope + no scope => Two directives which don’t require their own scope will use their parent’s scope
  • child scope + no scope => Both directives will share one single child scope
  • child scope + child scope => Both directives will share one single child scope
  • isolated scope + no scope => The isolated directive will use it’s own created isolated scope. The other directive will use its parent’s scope
  • isolated scope + child scope => Won’t work! Only one scope can be related to one element. Therefore these directives cannot be applied to the same element.
  • isolated scope + isolated scope => Won’t work! Only one scope can be related to one element. Therefore these directives cannot be applied to the same element.

One comment

  1. Hi There,

    Nice to be visiting your blog again, it has been months for me. Well this article that i’ve been waited for so long.

    I need to generate the word document dynamically using java code, included the necessary jar files, No compliation issue, but During run time am getting this error: Could not initialize class org.openxmlformats.schemas.wordprocessingml.x2006. main.CTDocume .using all these jar files: POI-3.6.jar, POI_3.9.jar, Poi-ooxml-3.5,Poi-ooxml-3.6,Poi-ooxml-3.7,Poi-ooxml-3.9,Poi-ooxml-
    schemas-3.6,Poi-ooxml-schemas-3.9.jar. using the XWPFdocument class. when my cursor get into that line XWPFDocument doc = new XWPFDocument();
    getting the above error.

    Follow my new blog if you interested in just tag along me in any social media platforms!

    Obrigado,
    Irene Hynes

Leave a Reply