11th Apr

The scope of directives in AngularJS

Monday, April 11, 2016 - 11:55
0
Author: Bartos Gergely

Directives

Directives are very powerful features of AngularJS. Imagine them as building re-usable components of any AngularJS application.

The scope

Every directive has a scope associated with it which is used for accessing data/methods inside the template and link function. Scope by default inherits from its parent scope, but this may not be desirable behavior, especially if you are building a re-usable widget.

You can change the default scope of directives by passing a configuration object known as directive definition object. A directive definition object (DDO) is a simple JavaScript object used for configuring the behaviour or the template of the directive.

The values of scope property decides how the actual scope is created and used inside a directive. The values can be either „false”, „true” or „{}”.

False (it is false by default)

Setting the value of the scope to false means the directive uses its parent scope. Therefore, any changes to the directive or controller will be in sync.

True

The directive gets a new scope by inheriting the parent scope. Any changes made to this new scope will not reflect back to the parent scope. However, since it is inherited from the parent scope, any changes made in the parent scope will be reflected in the directive scope.

Let’s see these examples:

or

In this case the scope is set to false. If we start editing the name, the header also changes:

After setting the value of the scope to true and edit the name again we got the following result:

https://jsfiddle.net/bartosg/e8en9r21/

It is important that directives cannot accidentally read or write properties in the parent scope. This is where isolated scope comes in.

{}

This will create an empty scope. The new scope also known as Isolated scope because it is completely detached, it will not be inherited from its parent scope. Leaving this scope empty is not particularly useful because your directive will have nothing available on its scope (other than the variables that you manually add).

To make local variables on your local scope available to the new directive’s scope, you’ll have to pass one of the following three aliases in the object:

Text Binding (Prefix: @)

Direct model binding (Prefix: =)

Behaviour binding (Prefix: &)

 

Text binding

Text bindings (or attribute bindings) are prefixed with @, and they are always strings. Whatever you write as attribute value, it will be parsed and returned as strings. Since DOM elements are always strings, we have to use double curly braces so that string interpolation can happen.

Example:

The value of firstName will be John. However if we change the attribute to first-name=”Hello {{name}}” the value changes to Hello John, and the output will be:

Another example: if we use first-name=”name” the value of DOM attribute „name" is simply the string name. If we use first-name=”{{name}}”, the value of the DOM attribute „name" is the interpolated value of {{name}} what in this case is „John”.

We can provide different mapping between property and attributes. This is done by giving a separate attribute name after the prefix:

The rule is simple: any string after the prefixes should match the attribute name.

Direct model binding

Direct model binding (or two-way binding) are prefixed by = and can be of any type. These work like actual bindings, any changes to a bound value will be reflected on everywhere. The most important point about „=” prefix is, it’ll always expect the attribute value to be the model name. That means you cannot provide an expression as the value of attribute mapped to „=” prefix, you cannot use {{}}.

Example:

Behaviour binding

Behaviour binding (expression binding or method binding) are prefixed by &. This is used to bind any methods from the parent scope to the directive scope.

Example:

Parent scope has a method called „updateLastName”. Through the „&” prefix, we bound the „updateLastName” method to a scope property named „myExpression”. So whenever the „myExpression()” method is executed inside the directive, it’ll basically invoke the „updateLastName” in the parent scope.

https://jsfiddle.net/bartosg/e8en9r21/2/

Prefix + „?”

If the parent scope property doesn't exist, and you try to set the value for that property in the directive, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You can avoid this behavior using „?” after the prefix, in order to flag the property as optional. E.g.: firstName: „@?”

For further information about understanding isolate scope have a look at these videos below:

https://egghead.io/lessons/angularjs-understanding-isolate-scope

https://egghead.io/lessons/angularjs-isolate-scope-attribute-binding

https://egghead.io/lessons/angularjs-isolate-scope-two-way-binding

https://egghead.io/lessons/angularjs-isolate-scope-expression-binding

Comments (0)
0