From 705f4bbf115d2408e33b25f56edbf1f383aabb82 Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Wed, 2 May 2012 21:08:02 -0700 Subject: [PATCH] fix($compile): attach scope to the directive element when templateUrl and replace=true We forgot to reattach the scope to the replacement element. This affected only directives that had templateUrl and replace:true properties. Reported on the mailing list: https://groups.google.com/forum/?fromgroups#!topic/angular/zwjLr1msS2Y http://jsfiddle.net/lukebayes/g9Sh9/ --- src/ng/compile.js | 13 +++++++++- test/ng/compileSpec.js | 54 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 17f49d685ae3..61e88df69e8d 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -852,13 +852,24 @@ function $CompileProvider($provide) { linkRootElement = linkQueue.pop(), cLinkNode = linkQueue.pop(), scope = linkQueue.pop(), - node = templateNode; + node = templateNode, + cLinkNodeJq = jqLite(cLinkNode); if (cLinkNode !== originalWidgetNode) { // it was cloned therefore we have to clone as well. node = JQLiteClone(templateNode); replaceWith(linkRootElement, jqLite(cLinkNode), node); } + + if (replace) { + if (cLinkNodeJq.data('$scope')) { + // if the original element before replacement had a new scope, the replacement should + // get it as well + jqLite(node).data('$scope', scope); + } + dealoc(cLinkNodeJq); + } + afterWidgetLinkFn(function() { beforeWidgetLinkFn(afterWidgetChildrenLinkFn, scope, node, rootElement, controller); }, scope, node, rootElement, controller); diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 74eaec8a8289..1c4a1d300f31 100644 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -991,6 +991,33 @@ describe('$compile', function() { } }; }); + $compileProvider.directive('tscope' + uppercase(name), function(log) { + return { + scope: true, + restrict: 'CA', + templateUrl: 'tscope.html', + compile: function() { + return function (scope, element) { + log(scope.$id); + expect(element.data('$scope')).toBe(scope); + }; + } + }; + }); + $compileProvider.directive('trscope' + uppercase(name), function(log) { + return { + scope: true, + replace: true, + restrict: 'CA', + templateUrl: 'trscope.html', + compile: function() { + return function (scope, element) { + log(scope.$id); + expect(element.data('$scope')).toBe(scope); + }; + } + }; + }); $compileProvider.directive('tiscope' + uppercase(name), function(log) { return { scope: {}, @@ -1034,6 +1061,33 @@ describe('$compile', function() { })); + it('should allow creation of new scopes for directives with templates', inject( + function($rootScope, $compile, log, $httpBackend) { + $httpBackend.expect('GET', 'tscope.html').respond('{{name}}; scopeId: {{$id}}'); + element = $compile('
')($rootScope); + $httpBackend.flush(); + expect(log).toEqual('LOG; log-002-001; 002'); + $rootScope.name = 'Jozo'; + $rootScope.$apply(); + expect(element.text()).toBe('Jozo; scopeId: 002'); + expect(element.find('span').scope().$id).toBe('002'); + })); + + + it('should allow creation of new scopes for replace directives with templates', inject( + function($rootScope, $compile, log, $httpBackend) { + $httpBackend.expect('GET', 'trscope.html'). + respond('

{{name}}; scopeId: {{$id}}

'); + element = $compile('
')($rootScope); + $httpBackend.flush(); + expect(log).toEqual('LOG; log-002-001; 002'); + $rootScope.name = 'Jozo'; + $rootScope.$apply(); + expect(element.text()).toBe('Jozo; scopeId: 002'); + expect(element.find('a').scope().$id).toBe('002'); + })); + + it('should allow creation of new isolated scopes for directives with templates', inject( function($rootScope, $compile, log, $httpBackend) { $httpBackend.expect('GET', 'tiscope.html').respond('');