0

When one directive (call it el2) is nested within another (call it el1), I cannot access variables "locally declared" in el1 (e.g. variables produced by ng-repeat, ng-init etc) from el2.

This fiddle demonstrates the issue. Code follows:

var myApp = angular.module('myApp',[]);

// define blue `el1` element which contains an `el2` child:
myApp.directive('el1', function() { 
    return {
        restrict: 'E',
        link: function($scope) {
        },
        replace: true,
        template: '<div ng-init="value1 = 1;">' +
            'value1: {{ value1 }}' +
            ' <el2></el2>' +
            '</div>',
        scope: {
        }
    };
});

// define green `el2` element:
myApp.directive('el2', function() {
    return {
        restrict: 'E',
        link: function($scope) {
        },
        replace: true,
        template: '<span ng-init="value2 = 2;">' +
            'value1: {{ value1 || "UNDEFINED" }} value2: {{ value2 }}</span>',
        scope: {
            value1: '='
        }
    };
});

How can I access value1 in the el2 directive? Is there any way that does not involve modifying the scope explicitly through the link function or controller?

6
  • 1
    Is el2 only used inside el1? If so, maybe having two directives is not the best thing, otherwise: could value1 be passed as an attribute? Commented Nov 17, 2014 at 13:16
  • 3
    have you tried this $parent.value1 in el2 directive. jsfiddle.net/zL47Ltsr/6 Commented Nov 17, 2014 at 13:16
  • @Grissom That works! But seems rather icky... Especially in a more complex case where it might be the parent's parent or when you might not even know which of your ancestors gave you the value? Commented Nov 17, 2014 at 13:18
  • 1
    @FabioF. Great solution. In fact, that is what I tried out first and then forgot about. The thing is that it did not work in one case because I forgot to change attribute names (called typeId and actionType) from camelCase to dash-delimiting! Stupid me! Do you want to post the solution? Commented Nov 17, 2014 at 13:26
  • @Domi you can answer yourself with the solution you've found ;) Commented Nov 17, 2014 at 13:28

1 Answer 1

1

So again: The problem is to share a variable between two nested directives.

The solution is simple and requires two and a half steps:

  1. Pass the name of the shared variable as an attribute to the inner (e.g. my-var="value1")
  2. Add that attribute to the inner directives scope set (e.g. scope: { myVar: '=' })
    • Make sure, you are using dash-delimiting case for the attribute name (e.g. my-var instead of myVar.

Updated JSFiddle here.

Now, the inner directive can access the outer directive's value of x.val as myValue1. As expected, the binding goes both ways.

Code:

var myApp = angular.module('myApp',[]);

var x = {
    val: 1
};

// define blue `el1` element which contains an `el2` child:
myApp.directive('el1', function() { 
    return {
        restrict: 'E',
        replace: true,
        controller: function($scope) {
            $scope.x = x;
        },
        template: '<div>' +
            'x.val: {{ x.val }}' +
            ' <el2 my-value1="x.val"></el2>' +
            '</div>'
    };
});

// define green `el2` element:
myApp.directive('el2', function() {
    return {
        restrict: 'E',
        replace: true,
        template: '<span ng-init="value2 = 2;">' +
            'myValue1: {{ myValue1 || "UNDEFINED" }} ' +
            '<button ng-click="myValue1 = myValue1+1;">+</button>' +
            'value2: {{ value2 }}' +
            '</span>',
        scope: {
            myValue1: '='
        }
    };
});

Thanks go to Fabio F. for pointing out that variable names can be simply transferred via attribute.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.