diff options
| -rw-r--r-- | src/ng/compile.js | 54 | ||||
| -rwxr-xr-x | test/ng/compileSpec.js | 52 |
2 files changed, 74 insertions, 32 deletions
diff --git a/src/ng/compile.js b/src/ng/compile.js index c49fbe28..040836f7 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -536,7 +536,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) @@ -747,12 +747,15 @@ 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. + * @param {Array.<Function>} preLinkFns + * @param {Array.<Function>} postLinkFns * @returns linkFn */ - function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection, originalReplaceDirective) { + function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection, + originalReplaceDirective, preLinkFns, postLinkFns) { var terminalPriority = -Number.MAX_VALUE, - preLinkFns = [], - postLinkFns = [], newScopeDirective = null, newIsolateScopeDirective = null, templateDirective = null, @@ -784,18 +787,24 @@ 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; + + // skip the check for directives with async templates, we'll check the derived sync directive when + // the template arrives + if (!directive.templateUrl) { + assertNoDuplicate('new/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); @@ -874,8 +883,9 @@ function $CompileProvider($provide) { if (directive.replace) { replaceDirective = 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 { @@ -1170,8 +1180,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, @@ -1179,7 +1189,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) @@ -1213,7 +1223,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]; @@ -1235,10 +1246,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; }). @@ -1253,9 +1261,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 2d6485d9..c6ba5480 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -1046,7 +1046,10 @@ describe('$compile', function() { priority: priority, compile: function() { log(name + '-C'); - return function() { log(name + '-L'); } + return { + pre: function() { log(name + '-PreL'); }, + post: function() { log(name + '-PostL'); } + } } }, options || {})); }); @@ -1075,7 +1078,8 @@ describe('$compile', function() { $rootScope.$digest(); expect(log).toEqual( 'first-C; FLUSH; second-C; last-C; third-C; ' + - 'third-L; first-L; second-L; last-L'); + 'first-PreL; second-PreL; last-PreL; third-PreL; ' + + 'third-PostL; first-PostL; second-PostL; last-PostL'); var span = element.find('span'); expect(span.attr('first')).toEqual(''); @@ -1099,7 +1103,8 @@ describe('$compile', function() { $rootScope.$digest(); expect(log).toEqual( 'iFirst-C; FLUSH; iSecond-C; iThird-C; iLast-C; ' + - 'iFirst-L; iSecond-L; iThird-L; iLast-L'); + 'iFirst-PreL; iSecond-PreL; iThird-PreL; iLast-PreL; ' + + 'iFirst-PostL; iSecond-PostL; iThird-PostL; iLast-PostL'); var div = element.find('div'); expect(div.attr('i-first')).toEqual(''); @@ -1124,7 +1129,8 @@ describe('$compile', function() { $rootScope.$digest(); expect(log).toEqual( 'first-C; FLUSH; second-C; last-C; third-C; ' + - 'third-L; first-L; second-L; last-L'); + 'first-PreL; second-PreL; last-PreL; third-PreL; ' + + 'third-PostL; first-PostL; second-PostL; last-PostL'); var span = element.find('span'); expect(span.attr('first')).toEqual(''); @@ -1149,7 +1155,8 @@ describe('$compile', function() { $rootScope.$digest(); expect(log).toEqual( 'iFirst-C; FLUSH; iSecond-C; iThird-C; iLast-C; ' + - 'iFirst-L; iSecond-L; iThird-L; iLast-L'); + 'iFirst-PreL; iSecond-PreL; iThird-PreL; iLast-PreL; ' + + 'iFirst-PostL; iSecond-PostL; iThird-PostL; iLast-PostL'); var div = element.find('div'); expect(div.attr('i-first')).toEqual(''); @@ -1264,6 +1271,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', + '<div ng-switch="i">' + + '<div ng-switch-when="1">i = 1</div>' + + '<div ng-switch-default>I dont know what `i` is.</div>' + + '</div>'); + + element = $compile('<div simple></div>')($rootScope); + + $rootScope.$apply(function() { + $rootScope.i = 1; + }); + + expect(element.html()).toContain('i = 1'); + }); + }); }); @@ -1482,7 +1518,7 @@ describe('$compile', function() { function($rootScope, $compile) { expect(function(){ $compile('<div class="iscope-a; scope-b"></div>'); - }).toThrowMinErr('$compile', 'multidir', 'Multiple directives [iscopeA, scopeB] asking for isolated scope on: ' + + }).toThrowMinErr('$compile', 'multidir', 'Multiple directives [iscopeA, scopeB] asking for new/isolated scope on: ' + '<div class="iscope-a; scope-b ng-isolate-scope ng-scope">'); }) ); @@ -2824,7 +2860,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. @@ -2850,7 +2886,7 @@ describe('$compile', function() { element = $compile('<div trans><span>unicorn!</span></div>')($rootScope); $rootScope.$apply(); - expect(log).toEqual('pre(unicorn!); post(unicorn!)'); + expect(log).toEqual('pre(); post(unicorn!)'); }); }); }); |
