geevee
geevee

Reputation: 5451

Angular - understanding directive isolated scope method

take a look at the following code:

html:

  <body ng-app="myApp">
    <div ng-controller="MainController">
      <input type="button" ng-click="talk()" value="outside directive" />
      <div my-element>
        <input type="button" ng-click="talk()" value="inside directive" />
      </div>
    </div>
  </body>

js:

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

app.controller('MainController', function($scope){
  $scope.talk = function() {
    alert('HELLO1');
  }
});

app.directive('myElement', function(){
  return {
    restrict: 'EA',
    scope: {},
    controller: function($scope) {
      $scope.talk = function() {
        alert('HELLO2');
      }
    }
  };
});

as you can see, there's a controller, which nests a directive.

there are 2 buttons, one in controller level (outside of directive), and one is inside the directive my-element.

the main controller defines a scope method talk, the nested directive controller also defines a method - talk - but keep in mind that directive has isolated scope (i'd expect that talk method won't be inherited into directive's scope).

both buttons result an alert of 'HELLO 1', while i expected the second button (inside directive) to alert 'HELLO 2' as defined in directive controller, but it doesn't - WHY?

what am i missing here? how could i get a result when the second button will alert 'HELLO 2' but with the same method name ("talk") ?

thanks all

Upvotes: 2

Views: 107

Answers (2)

Joshua Kelly
Joshua Kelly

Reputation: 1063

This will work for you

<body ng-app="myApp">
    <div ng-controller="MainController">
        <input type="button" ng-click="talk()" value="outside directive" />
        <div my-element></div>
    </div>
</body>

app.directive('myElement', function(){
    return {
        restrict: 'A',
        template: '<input type="button" ng-click="talk()" value="inside directive">',
        replace: true,
        scope: {},
        controller: function($scope) {
            $scope.talk = function() {
                alert('HELLO2');
            }
        }
    };
});

Upvotes: 0

Joe Enzminger
Joe Enzminger

Reputation: 11190

If you want the inner content to use the directive scope, you need to use manual transclusion:

app.directive('myElement', function(){
  return {
    restrict: 'EA',
    scope: {},
    transclude: true,
    link: function(scope, element, attr, ctrl, transclude) {
         transclude(scope, function(clone, scope) {
             element.append(clone);
         });
    },
    controller: function($scope) {
      $scope.talk = function() {
        alert('HELLO2');
      }
    }
  };
});

By default, transcluded content uses a sibling of the directive scope. I actually don't know how angular handles DOM content for directives that don't use transclude (which is what makes this an interesting question), but I would assume from the behavior you are seeing that those elements use the directive's parent scope by default.

Upvotes: 2

Related Questions