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!)');        });      });    }); | 
