diff --git a/src/ng/compile.js b/src/ng/compile.js index 7a2ee4e7fcf8..44bd31983da6 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -526,7 +526,7 @@ function $CompileProvider($provide) { directives = collectDirectives(nodeList[i], [], attrs, i == 0 ? maxPriority : undefined, ignoreDirective); nodeLinkFn = (directives.length) - ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement) + ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, null, [], []) : null; childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes || !nodeList[i].childNodes.length) @@ -734,12 +734,13 @@ function $CompileProvider($provide) { * scope argument is auto-generated to the new child of the transcluded parent scope. * @param {JQLite} jqCollection If we are working on the root of the compile tree then this * argument has the root jqLite array so that we can replace nodes on it. + * @param {Object=} ignoreDirective An optional directive that will be ignored when compiling + * the transclusion. * @returns linkFn */ - function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection, originalReplaceDirective) { + function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, + jqCollection, ignoreDirective, preLinkFns, postLinkFns) { var terminalPriority = -Number.MAX_VALUE, - preLinkFns = [], - postLinkFns = [], newScopeDirective = null, newIsolateScopeDirective = null, templateDirective = null, @@ -748,7 +749,6 @@ function $CompileProvider($provide) { directiveName, $template, transcludeDirective, - replaceDirective = originalReplaceDirective, childTranscludeFn = transcludeFn, controllerDirectives, linkFn, @@ -771,18 +771,22 @@ function $CompileProvider($provide) { } if (directiveValue = directive.scope) { - assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode); - if (isObject(directiveValue)) { - safeAddClass($compileNode, 'ng-isolate-scope'); - newIsolateScopeDirective = directive; - } - safeAddClass($compileNode, 'ng-scope'); newScopeDirective = newScopeDirective || directive; + + if (!directive.templateUrl) { + assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode); + if (isObject(directiveValue)) { + safeAddClass($compileNode, 'ng-isolate-scope'); + newIsolateScopeDirective = directive; + } + safeAddClass($compileNode, 'ng-scope'); + } } directiveName = directive.name; - if (directiveValue = directive.controller) { + if (!directive.templateUrl && directive.controller) { + directiveValue = directive.controller; controllerDirectives = controllerDirectives || {}; assertNoDuplicate("'" + directiveName + "' controller", controllerDirectives[directiveName], directive, $compileNode); @@ -801,7 +805,7 @@ function $CompileProvider($provide) { replaceWith(jqCollection, jqLite(sliceArgs($template)), compileNode); childTranscludeFn = compile($template, transcludeFn, terminalPriority, - replaceDirective && replaceDirective.name); + ignoreDirective && ignoreDirective.name); } else { $template = jqLite(JQLiteClone(compileNode)).contents(); $compileNode.html(''); // clear contents @@ -820,7 +824,7 @@ function $CompileProvider($provide) { directiveValue = denormalizeTemplate(directiveValue); if (directive.replace) { - replaceDirective = directive; + ignoreDirective = directive; $template = jqLite('
' + trim(directiveValue) + '
').contents(); @@ -859,10 +863,11 @@ function $CompileProvider($provide) { templateDirective = directive; if (directive.replace) { - replaceDirective = directive; + ignoreDirective = directive; } - nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), - nodeLinkFn, $compileNode, templateAttrs, jqCollection, childTranscludeFn); + + nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, + templateAttrs, jqCollection, childTranscludeFn, preLinkFns, postLinkFns); ii = directives.length; } else if (directive.compile) { try { @@ -1143,8 +1148,8 @@ function $CompileProvider($provide) { } - function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs, - $rootElement, childTranscludeFn) { + function compileTemplateUrl(directives, $compileNode, tAttrs, + $rootElement, childTranscludeFn, preLinkFns, postLinkFns) { var linkQueue = [], afterTemplateNodeLinkFn, afterTemplateChildLinkFn, @@ -1152,7 +1157,7 @@ function $CompileProvider($provide) { origAsyncDirective = directives.shift(), // The fact that we have to copy and patch the directive seems wrong! derivedSyncDirective = extend({}, origAsyncDirective, { - controller: null, templateUrl: null, transclude: null, scope: null, replace: null + templateUrl: null, transclude: null, replace: null }), templateUrl = (isFunction(origAsyncDirective.templateUrl)) ? origAsyncDirective.templateUrl($compileNode, tAttrs) @@ -1186,7 +1191,8 @@ function $CompileProvider($provide) { directives.unshift(derivedSyncDirective); - afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn, $compileNode, origAsyncDirective); + afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, + childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns); forEach($rootElement, function(node, i) { if (node == compileNode) { $rootElement[i] = $compileNode[0]; @@ -1208,10 +1214,7 @@ function $CompileProvider($provide) { replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); } - afterTemplateNodeLinkFn( - beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller), - scope, linkNode, $rootElement, controller - ); + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller); } linkQueue = null; }). @@ -1226,9 +1229,7 @@ function $CompileProvider($provide) { linkQueue.push(rootElement); linkQueue.push(controller); } else { - afterTemplateNodeLinkFn(function() { - beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller); - }, scope, node, rootElement, controller); + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller); } }; } diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index d26438783d70..43bcd2433825 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -1264,6 +1264,35 @@ describe('$compile', function() { expect(element.text()).toBe('boom!1|boom!2|'); }); }); + + + it('should support templateUrl with replace', function() { + // a regression https://github.com/angular/angular.js/issues/3792 + module(function($compileProvider) { + $compileProvider.directive('simple', function() { + return { + templateUrl: '/some.html', + replace: true + }; + }); + }); + + inject(function($templateCache, $rootScope, $compile) { + $templateCache.put('/some.html', + '
' + + '
i = 1
' + + '
I dont know what `i` is.
' + + '
'); + + element = $compile('
')($rootScope); + + $rootScope.$apply(function() { + $rootScope.i = 1; + }); + + expect(element.html()).toContain('i = 1'); + }); + }); }); @@ -2824,7 +2853,7 @@ describe('$compile', function() { }); - it('should make the result of a transclusion available to the parent directive in pre- and post- linking phase (templateUrl)', + it('should make the result of a transclusion available to the parent directive in post- linking phase (templateUrl)', function() { // when compiling an async directive the transclusion is always processed before the directive // this is different compared to sync directive. delaying the transclusion makes little sense. @@ -2834,13 +2863,8 @@ describe('$compile', function() { return { transclude: true, templateUrl: 'trans.html', - link: { - pre: function($scope, $element) { - log('pre(' + $element.text() + ')'); - }, - post: function($scope, $element) { - log('post(' + $element.text() + ')'); - } + link: function($scope, $element) { + log('post(' + $element.text() + ')'); } }; }); @@ -2850,7 +2874,7 @@ describe('$compile', function() { element = $compile('
unicorn!
')($rootScope); $rootScope.$apply(); - expect(log).toEqual('pre(unicorn!); post(unicorn!)'); + expect(log).toEqual('post(unicorn!)'); }); }); });