How does one preserve scope with nested directives?

starchild

My goal is to create a flexible set of directives for reusable and lightweight UI elements. Each has an isolated scope, and many of them transclude content. I want each directive to be a black box - the user ideally wouldn't need to know whether it nests another directive internally when writing the content to be transcluded.

According to the Angular guide to directives:

The transclude option changes the way scopes are nested. It makes it so that the contents of a transcluded directive have whatever scope is outside the directive, rather than whatever scope is on the inside. In doing so, it gives the contents access to the outside scope.

I have found that this works as described when using a single directive. However, if there is another directive nested in that one that also transcludes the content, then the transcluded content is resolved within the scope of the outer directive, rather than the scope that is on the outside. This is a problem, because it prevents users from knowing in what scope their transcluded content will be resolved!

For example: (fiddle)

.controller('main', function ($scope) {
    $scope.value = '"main"';
    $scope.expected = $scope.value;
})

.directive('outer', function () {
    return {
        restrict: 'E',
        replace: true,
        transclude: true,
        scope: { expected:'=' },
        controller: function ($scope) {
            $scope.value = '"outer"';
        },
        template: '<div><inner expected="expected"><span ng-transclude></span></inner></div>'
    };
})

.directive('inner', function () {
    return {
        restrict: 'E',
        replace: true,
        transclude: true,
        scope: { expected:'=' },
        controller: function ($scope) {
            $scope.value = '"inner"';
        },
        template: '<div><span>\'value\' is expected to be resolved in scope {{expected}}, and is resolved in scope </span><span ng-transclude></span></div>'
    };
})

And the HTML:

<div ng-controller="main">
    <inner expected="value">
        <span>{{value}}</span>
    </inner>
    <hr/>
    <outer expected="value">
        <span>{{value}}</span>
    </outer>
</div>

Inside the <inner></inner> element {{value}} is evaluated within the parent scope as "main" (as expected). However, inside the <outer></outer> element {{value}} is evaluated within the isolated scope of outer as "outer" (not expected). In this way, the template of the directive can affect the scope in which the transcluded content is resolved!

Is there any way to work around this issue?

starchild

After some tinkering I found a solution. I created two new directives to replace the default ng-transcude, and a helper service that stores the state shared between the directives. Together they allow the deep transclusion that I was looking for.

The first stores $transclude into the service; it must be used within every directive that can be given transcludible content in a template:

controller: ['$transclude', 'TransclusionHelper', function($transclude,TransclusionHelper) {
    TransclusionHelper.setTransclusionFn($transclude);
}],

The second performs the transclusion of the content to its final location; it need not be used in directives that only pass through their transcluded content to a child:

link: ['$element','TransclusionHelper', function($element,TransclusionHelper) {
    TransclusionHelper.transclude(function(clone) {
        $element.empty();
        $element.append(clone);
    });
}],

Some finesse is required in the service to manage state; if several calls to setTransclusionFn are made before a call to transclude, only the first should be stored and used when transclude is called.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How does one preserve scope with nested directives?

From Dev

Scope Isolation & nested directives

From Dev

angularjs inheriting scope in nested directives

From Dev

AngularJS : Nested Directives and Scope Inheritance

From Dev

Nested Angular directives triggering scope functions on parents

From Dev

Passing params to nested directives with isolated scope

From Dev

AngularJS : Scope is not shared between nested transcluded directives

From Dev

two directives creating new inherited and isolated scope - which one does the element get

From Dev

How do I get access to a specific parent scope when I have nested directives?

From Dev

Directives scope variable does not work in Jade

From Dev

How does one fix a "Variable not in scope" error?

From Dev

AngularJS: how to optimize nested directives

From Dev

AngularJS: how to optimize nested directives

From Dev

Scope in directives

From Dev

Scope in directives

From Dev

Angular How to access controller scope from directives

From Dev

Angular:How to pass scope data to directives

From Dev

How to distinguish multiple directives in the same $scope?

From Dev

Binding functions through nested directives with isolated scope failing in Angular 1.4

From Dev

Calling a parent scope function from deeply nested directives

From Dev

Nested directives, scope inheritance, and watching values between parent and child

From Dev

How does scope gets affected in nested functions in C?

From Dev

How does one prevent nested function calls?

From Dev

How does AngularJS compile directives?

From Dev

How does AngularJS compile directives?

From Dev

Can multiple directives for one element share an isolated scope?

From Dev

Can multiple directives for one element share an isolated scope?

From Dev

How to stop propagation of & functions into nested directives

From Dev

Bigquery: how to preserve nested data in derived tables?

Related Related

  1. 1

    How does one preserve scope with nested directives?

  2. 2

    Scope Isolation & nested directives

  3. 3

    angularjs inheriting scope in nested directives

  4. 4

    AngularJS : Nested Directives and Scope Inheritance

  5. 5

    Nested Angular directives triggering scope functions on parents

  6. 6

    Passing params to nested directives with isolated scope

  7. 7

    AngularJS : Scope is not shared between nested transcluded directives

  8. 8

    two directives creating new inherited and isolated scope - which one does the element get

  9. 9

    How do I get access to a specific parent scope when I have nested directives?

  10. 10

    Directives scope variable does not work in Jade

  11. 11

    How does one fix a "Variable not in scope" error?

  12. 12

    AngularJS: how to optimize nested directives

  13. 13

    AngularJS: how to optimize nested directives

  14. 14

    Scope in directives

  15. 15

    Scope in directives

  16. 16

    Angular How to access controller scope from directives

  17. 17

    Angular:How to pass scope data to directives

  18. 18

    How to distinguish multiple directives in the same $scope?

  19. 19

    Binding functions through nested directives with isolated scope failing in Angular 1.4

  20. 20

    Calling a parent scope function from deeply nested directives

  21. 21

    Nested directives, scope inheritance, and watching values between parent and child

  22. 22

    How does scope gets affected in nested functions in C?

  23. 23

    How does one prevent nested function calls?

  24. 24

    How does AngularJS compile directives?

  25. 25

    How does AngularJS compile directives?

  26. 26

    Can multiple directives for one element share an isolated scope?

  27. 27

    Can multiple directives for one element share an isolated scope?

  28. 28

    How to stop propagation of & functions into nested directives

  29. 29

    Bigquery: how to preserve nested data in derived tables?

HotTag

Archive