aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ng/directive/ngTransclude.js11
-rwxr-xr-xtest/ng/compileSpec.js89
2 files changed, 97 insertions, 3 deletions
diff --git a/src/ng/directive/ngTransclude.js b/src/ng/directive/ngTransclude.js
index c15b77cb..668f8033 100644
--- a/src/ng/directive/ngTransclude.js
+++ b/src/ng/directive/ngTransclude.js
@@ -49,9 +49,14 @@
*
*/
var ngTranscludeDirective = ngDirective({
- controller: ['$transclude', '$element', function($transclude, $element) {
- $transclude(function(clone) {
- $element.append(clone);
+ controller: ['$transclude', '$element', '$scope', function($transclude, $element, $scope) {
+ // use evalAsync so that we don't process transclusion before directives on the parent element even when the
+ // transclusion replaces the current element. (we can't use priority here because that applies only to compile fns
+ // and not controllers
+ $scope.$evalAsync(function() {
+ $transclude(function(clone) {
+ $element.append(clone);
+ });
});
}]
});
diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js
index 97a58c10..c7821878 100755
--- a/test/ng/compileSpec.js
+++ b/test/ng/compileSpec.js
@@ -2331,6 +2331,95 @@ describe('$compile', function() {
expect(asyncCtrlSpy).toHaveBeenCalledOnce();
});
});
+
+
+
+ it('should instantiate controllers in the parent->child order when transluction, templateUrl and replacement ' +
+ 'are in the mix', function() {
+ // When a child controller is in the transclusion that replaces the parent element that has a directive with
+ // a controller, we should ensure that we first instantiate the parent and only then stuff that comes from the
+ // transclusion.
+ //
+ // The transclusion moves the child controller onto the same element as parent controller so both controllers are
+ // on the same level.
+
+ module(function() {
+ directive('parentDirective', function() {
+ return {
+ transclude: true,
+ replace: true,
+ templateUrl: 'parentDirective.html',
+ controller: function (log) { log('parentController'); }
+ };
+ });
+ directive('childDirective', function() {
+ return {
+ require: '^parentDirective',
+ templateUrl: 'childDirective.html',
+ controller : function(log) { log('childController'); }
+ };
+ });
+ });
+
+ inject(function($templateCache, log, $compile, $rootScope) {
+ $templateCache.put('parentDirective.html', '<div ng-transclude>parentTemplateText;</div>');
+ $templateCache.put('childDirective.html', '<span>childTemplateText;</span>');
+
+ element = $compile('<div parent-directive><div child-directive></div>childContentText;</div>')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('parentController; childController');
+ expect(element.text()).toBe('parentTemplateText;childTemplateText;childContentText;')
+ });
+ });
+
+
+ it('should instantiate controllers in the parent->child->baby order when nested transluction, templateUrl and ' +
+ 'replacement are in the mix', function() {
+ // similar to the test above, except that we have one more layer of nesting and nested transclusion
+
+ module(function() {
+ directive('parentDirective', function() {
+ return {
+ transclude: true,
+ replace: true,
+ templateUrl: 'parentDirective.html',
+ controller: function (log) { log('parentController'); }
+ };
+ });
+ directive('childDirective', function() {
+ return {
+ require: '^parentDirective',
+ transclude: true,
+ replace: true,
+ templateUrl: 'childDirective.html',
+ controller : function(log) { log('childController'); }
+ };
+ });
+ directive('babyDirective', function() {
+ return {
+ require: '^childDirective',
+ templateUrl: 'babyDirective.html',
+ controller : function(log) { log('babyController'); }
+ };
+ });
+ });
+
+ inject(function($templateCache, log, $compile, $rootScope) {
+ $templateCache.put('parentDirective.html', '<div ng-transclude>parentTemplateText;</div>');
+ $templateCache.put('childDirective.html', '<span ng-transclude>childTemplateText;</span>');
+ $templateCache.put('babyDirective.html', '<span>babyTemplateText;</span>');
+
+ element = $compile('<div parent-directive>' +
+ '<div child-directive>' +
+ 'childContentText;' +
+ '<div baby-directive>babyContent;</div>' +
+ '</div>' +
+ '</div>')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('parentController; childController; babyController');
+ expect(element.text()).toBe('parentTemplateText;childTemplateText;childContentText;babyTemplateText;')
+ });
+ });
});