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.
If a directive is not instructed to provide a new scope for itself, it will inherit the parent scope. In the case that this is not desirable behavior, you will need to create an isolate scope for that directive, and inside that isolate scope, you can define a whitelist of parent scope elements that the directive will need.
To declare a directive with an isolate scope, simply pass an empty object literal as the scope
property:
With this, there will be no inheritance from the parent scope in MainCtrl
, and the directive will be unable to use methods or variables in the parent scope.
If you want to pass a read-only value to the directive, you will use @
inside the isolate scope declaration to indicate that a named attribute of the relevant HTML element contains a value that should be incorporated into the directive's isolate scope. This can be done as follows:
With this, the scope inside the directive now contains an innerval
attribute with the value of outerval
in the parent scope. AngularJS evaluates the expression string, and the result is provided to the directive's scope. Setting the value of the variable does nothing to the parent scope or the attribute in the HTML; it is merely copied into the scope of the directive.
While this approach is useful, it doesn't involve data binding, which you have come to love in AngularJS, and it isn't all that more convenient than passing in a static string value. What is far more likely to be useful to you is a true whitelist of the data binding from the parent scope. This can be accomplished with the =
definition, as follows:
Here, you are instructing the child directive scope to examine the parent controller scope, and bind the parent outerval
attribute inside the child scope, aliased as the innerval
attribute. Full data binding between scopes is supported, and all unnamed attributes and methods in the parent scope are ignored.
Taking a step further, methods can also be pulled down from the parent scope for use in the directive. In the same way that a model variable can be bound to the child scope, you can alias methods that are defined in the parent scope to be invoked from the child scope but are still in the parent scope context. This is accomplished with the &
definition, as follows:
Here, you are instructing the child directive to evaluate the expression passed to the myattr
attribute within the context of the parent controller. In this case, the expression will invoke the func()
method, but any valid AngularJS expression will also work. You can invoke it as you would invoke any other scope method, including parameters as required.
Isolate scope is entirely managed within the scope
attribute in the directive's returned definition object. Using @
, =
, and &
, you are instructing the directive to ignore the scopes it would normally inherit, and only utilize data, variables, and methods that you have provided interfaces for instead.
If the directive is designed as a specific modifier for an aspect of your application, you might find that using isolate scope isn't necessary. On the other hand, if you're building a reusable, monolithic component that can be reused across multiple applications, it is unlikely that the directive will be using the parent scope in which it is used. Hence, isolate scope will be significantly more useful.