Paulius K.
Paulius K.

Reputation: 883

AngularJS scopes

I have a weird case of angular scope mixup. Here's the plnkr: http://plnkr.co/edit/o8cyZXkHX8Lt9Vkbn0xm

The transcluded scope does not resolve appCtrl.testString, which is strange, because transcluded content should have the outside scope. What's even more strange is that num gets resolved correctly.

Also, data-test-attr gets the correct value on the element that ng-controller is defined.

This is a minimal working example, so solutions with reordering the elements or defining a scope in a different place do not really suit me. I'd rather hack the repeatedDirective somehow, if that's at all possible.

Here's the code:

index.html

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="[email protected]" data-semver="1.4.3" src="https://code.angularjs.org/1.4.3/angular.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <repeated-directive ng-repeat="num in [1, 2, 3, 4, 5]" ng-controller="AppController as appCtrl" data-test-attr="{{appCtrl.testString}}">
      <div>{{num}} - {{appCtrl.testString}}</div>
    </repeated-directive>
  </body>

</html>

script.js

angular.module('app', [])
  .controller('AppController', AppController)
  .directive('repeatedDirective', repeatedDirective);

function AppController($scope) {
  this.testString = 'Controller value';
}

function repeatedDirective() {
  return {
    transclude: true,
    template: '<div ng-transclude></div>'
  };
}

Upvotes: 1

Views: 70

Answers (2)

Arno_Geismar
Arno_Geismar

Reputation: 2330

Your controller is not in scope of your directive:

this fixes it without changing anything in your html:

angular.module('app', [])
  .controller('AppController', AppController)
  .directive('repeatedDirective', repeatedDirective);

function AppController($scope) {
  this.testString = 'Controller value';
}

function repeatedDirective() {
  return {
    transclude: true,
    template: '<div></div>',
    link: function(scope, element, attrs, ctrl, transclude) {
      transclude(scope, function(clone, scope) {
        element.append(clone);
      });
    }
  };
}

http://plnkr.co/edit/LsRfyw98f4BP4G72Bgd6?p=preview

This way your transclusion does not use a seperate scope but takes the scope of the controller.

e voila

for more information on what exactly is happening I will include a reference blog :

http://angular-tips.com/blog/2014/03/transclusion-and-scopes/

Upvotes: 2

Mike Vranckx
Mike Vranckx

Reputation: 5577

Within your ng-repeat, you have your scope of [1, 2, 3, 4, 5] and not the appCtrl which explains the empty value of testString (actually it is unexisting). You should access the $parent to be able to have your appCtrl scope.

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="[email protected]" data-semver="1.4.3" src="https://code.angularjs.org/1.4.3/angular.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <repeated-directive ng-repeat="num in [1, 2, 3, 4, 5]" ng-controller="AppController as appCtrl" data-test-attr="{{appCtrl.testString}}">
      <div>{{num}} - {{$parent.appCtrl.testString}}</div>
    </repeated-directive>
  </body>

</html>

http://plnkr.co/edit/qc3j0nsJZKypXSsqMEqx

Upvotes: 0

Related Questions