Alex Churchill
Alex Churchill

Reputation: 4957

How can I bind scope property of transcluded element to parent?

I'm attempting to create a reusable parent container directive. What I want is something like the following:

<parent title="Parent title">
    <child></child>
</parent>

where I can have the child elements change a value in the parent's scope.

I've attempted this binding as follows (see this fiddle):

myApp.directive('parent', function() {
    return {
        scope: {'title': '@'},
        transclude: true,
        // Manually transclude so we set parent scope to be this scope.
        link: function(scope, element, attrs, ctrl, transclude) {
            transclude(scope.$new(), function(content) {
                element.append(content);
            });
        },
        restrict: 'EA',
        template: '<div><b>PARENT:</b> {{title}}</div>',
        controller: function($scope) {
            $scope.inherited = true;
            $scope.$watch('inherited', function(newValue, oldValue) {
                if(!newValue) {
                    console.log('Parent: inherited switched');
                }
            });
        }
    }
});

myApp.directive('child', function() {
    return {
        restrict: 'EA',
        scope:{
            inherited: '='
        },
        template: '<div><b>Child:</b> inherited attribute = {{inherited}}</div>',
        controller: function($scope) {
            // Why is inherited not bound to parent here?
            console.log($scope.inherited);
            // It obviously exists in the parent...
            console.log($scope.$parent.inherited);
        }
    }
});

From my understanding of the API, setting an object hash scope with inherited: '=' should bind to the parent property, but as you can see in the fiddle, it doesn't.

I have two questions:

  1. Why is inherited not bound to the parent property?
  2. How can I achieve this message passing?

Caveats:

Thanks for any guidance.

Upvotes: 0

Views: 171

Answers (1)

dave
dave

Reputation: 64657

You can either do:

<child inherited="inherited"></child>

where you actually pass in the inherited attribute, since that is what it is looking for when you do

scope:{
        inherited: '='
    },

Or you could do:

myApp.directive('child', function() {
return {
    restrict: 'EA',
    scope: false,

so that it uses it's parent's scope.

Either way, you are likely to run into some issues binding to a primitive. You will probably save yourself a lot of headache by making inherited an object, passing the object around, and when you need to display it show the object property:

JS:

$scope.inherited = {is: true};

HTML:

{{inherited.is}}

But then keep passing around the whole object.

http://jsfiddle.net/GQX9z/1/

Upvotes: 1

Related Questions