Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS Transclusion Directive with ngRepeat results in mixed scope

Tags:

angularjs

AngularJS has the super nifty ngTransclude directive, which replaces html in your directive's template with html from the controller's template. If you're using an isolated scope in your directive, you can access variables from the controller's scope using ngTransclude.

I was attempting to do this when I ended up with a seemingly random result. ngTransclude inside of a ngRepeat returned the value from the directive's scope instead of the controller's scope.

Going off of the AngularJS documentation, I created a Plunker: http://plnkr.co/edit/GtrYtGoy2fnvgkwLFAGN?p=preview

JS

angular.module('docsTransclusionExample', [])
  .controller('Controller', ['$scope', function($scope) {
    $scope.names = ['Tobias', 'Funke'];
  }])
  .directive('myDialog', function() {
    return {
      restrict: 'E',
      transclude: true,
      scope: {},
      templateUrl: 'my-dialog.html',
      link: function (scope, element) {
        scope.names = ['Jeff', 'Bridges'];
      }
    };
  });

index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example - example-example87-production</title>


  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
  <script src="script.js"></script>



</head>
<body ng-app="docsTransclusionExample">
    <div ng-controller="Controller">
    <my-dialog>Check out the contents, {{names}}!</my-dialog>
  </div>
</body>
</html>

my-dialog.html

<div class="alert" ng-transclude></div>
<div ng-repeat="name in names">
  <div class="alert" ng-transclude></div>
  {{name}}
</div>
<div class="alert" ng-transclude></div>

This code returns:

Check out the contents, ["Tobias","Funke"]!
Check out the contents, ["Jeff","Bridges"]!
Jeff
Check out the contents, ["Jeff","Bridges"]!
Bridges
Check out the contents, ["Tobias","Funke"]!

According to the documentation I've read, and this transclusion and scopes article I found for transclusion and scope, transclusion should ONLY take in the controller's scope, meaning the middle two "Check out the contents, {{names}}!" should read the same as the outer two.

Further experimentation had me changing the AngularJS version from 1.2.15 to the 1.3.0 rc

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.1/angular.min.js"></script>

which results in the correct (as far as I understand it) output:

Check out the contents, ["Tobias","Funke"]!
Check out the contents, ["Tobias","Funke"]!
Jeff
Check out the contents, ["Tobias","Funke"]!
Bridges
Check out the contents, ["Tobias","Funke"]!

Is there a workaround for this problem that I can use with 1.2.15 or am I stuck when using this version? What is the correct behavior supposed to be?

like image 796
Mick Roper Avatar asked Nov 01 '22 17:11

Mick Roper


1 Answers

From changelog of 1.3.0b11:

ngRepeat: ensure that the correct (transcluded) scope is used (b87e5fc0)

Same for ng-if (has the same strange different behavior when switching between 1.2.15 and 1.3.0-rc.1 in your plunker).

So the correct one is when using 1.3.0-rc.1.

like image 146
przno Avatar answered Nov 11 '22 02:11

przno