fix($compile): instantiate controlers when re-entering compilation

When we re-enter compilation either due to async directive templates or element transclude directive
we need to keep track of controllers to instantiate during linking.

This piece of info was missing when re-entering compilation and that's what this commit fixes.

I also reordered the properties in the previousCompileContext object.

Closes #4434
Closes #4616
This commit is contained in:
Igor Minar 2013-10-21 17:38:43 -07:00
parent e57d5b89ca
commit faf5b980da
2 changed files with 64 additions and 8 deletions

View file

@ -1117,16 +1117,16 @@ function $CompileProvider($provide) {
var terminalPriority = -Number.MAX_VALUE, var terminalPriority = -Number.MAX_VALUE,
newScopeDirective, newScopeDirective,
controllerDirectives = previousCompileContext.controllerDirectives,
newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
templateDirective = previousCompileContext.templateDirective, templateDirective = previousCompileContext.templateDirective,
transcludeDirective = previousCompileContext.transcludeDirective,
$compileNode = templateAttrs.$$element = jqLite(compileNode), $compileNode = templateAttrs.$$element = jqLite(compileNode),
directive, directive,
directiveName, directiveName,
$template, $template,
transcludeDirective = previousCompileContext.transcludeDirective,
replaceDirective = originalReplaceDirective, replaceDirective = originalReplaceDirective,
childTranscludeFn = transcludeFn, childTranscludeFn = transcludeFn,
controllerDirectives,
linkFn, linkFn,
directiveValue; directiveValue;
@ -1191,9 +1191,10 @@ function $CompileProvider($provide) {
childTranscludeFn = compile($template, transcludeFn, terminalPriority, childTranscludeFn = compile($template, transcludeFn, terminalPriority,
replaceDirective && replaceDirective.name, { replaceDirective && replaceDirective.name, {
controllerDirectives: controllerDirectives,
newIsolateScopeDirective: newIsolateScopeDirective, newIsolateScopeDirective: newIsolateScopeDirective,
transcludeDirective: transcludeDirective, templateDirective: templateDirective,
templateDirective: templateDirective transcludeDirective: transcludeDirective
}); });
} else { } else {
$template = jqLite(jqLiteClone(compileNode)).contents(); $template = jqLite(jqLiteClone(compileNode)).contents();
@ -1259,9 +1260,10 @@ function $CompileProvider($provide) {
nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
templateAttrs, jqCollection, childTranscludeFn, preLinkFns, postLinkFns, { templateAttrs, jqCollection, childTranscludeFn, preLinkFns, postLinkFns, {
controllerDirectives: controllerDirectives,
newIsolateScopeDirective: newIsolateScopeDirective, newIsolateScopeDirective: newIsolateScopeDirective,
transcludeDirective: transcludeDirective, templateDirective: templateDirective,
templateDirective: templateDirective transcludeDirective: transcludeDirective
}); });
ii = directives.length; ii = directives.length;
} else if (directive.compile) { } else if (directive.compile) {

View file

@ -2282,6 +2282,60 @@ describe('$compile', function() {
}); });
it('should get required controller via linkingFn (template)', function() {
module(function() {
directive('dirA', function() {
return {
controller: function() {
this.name = 'dirA';
}
};
});
directive('dirB', function(log) {
return {
require: 'dirA',
template: '<p>dirB</p>',
link: function(scope, element, attrs, dirAController) {
log('dirAController.name: ' + dirAController.name);
}
};
});
});
inject(function(log, $compile, $rootScope) {
element = $compile('<div dir-a dir-b></div>')($rootScope);
expect(log).toEqual('dirAController.name: dirA');
});
});
it('should get required controller via linkingFn (templateUrl)', function() {
module(function() {
directive('dirA', function() {
return {
controller: function() {
this.name = 'dirA';
}
};
});
directive('dirB', function(log) {
return {
require: 'dirA',
templateUrl: 'dirB.html',
link: function(scope, element, attrs, dirAController) {
log('dirAController.name: ' + dirAController.name);
}
};
});
});
inject(function(log, $compile, $rootScope, $templateCache) {
$templateCache.put('dirB.html', '<p>dirB</p>');
element = $compile('<div dir-a dir-b></div>')($rootScope);
$rootScope.$digest();
expect(log).toEqual('dirAController.name: dirA');
});
});
it('should support controllerAs', function() { it('should support controllerAs', function() {
module(function() { module(function() {
directive('main', function() { directive('main', function() {