diff options
| -rw-r--r-- | src/AngularPublic.js | 4 | ||||
| -rw-r--r-- | src/ng/directive/ngInclude.js | 34 | ||||
| -rw-r--r-- | test/ng/directive/ngIncludeSpec.js | 40 | 
3 files changed, 71 insertions, 7 deletions
| diff --git a/src/AngularPublic.js b/src/AngularPublic.js index d2c325c5..14fe25ae 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -28,6 +28,7 @@      ngHideDirective,      ngIfDirective,      ngIncludeDirective, +    ngIncludeFillContentDirective,      ngInitDirective,      ngNonBindableDirective,      ngPluralizeDirective, @@ -181,6 +182,9 @@ function publishExternalAPI(angular){              ngRequired: requiredDirective,              ngValue: ngValueDirective          }). +        directive({ +          ngInclude: ngIncludeFillContentDirective +        }).          directive(ngAttributeAliasDirectives).          directive(ngEventDirectives);        $provide.provider({ diff --git a/src/ng/directive/ngInclude.js b/src/ng/directive/ngInclude.js index b721aa23..d6b38663 100644 --- a/src/ng/directive/ngInclude.js +++ b/src/ng/directive/ngInclude.js @@ -147,13 +147,14 @@   * @description   * Emitted every time the ngInclude content is reloaded.   */ -var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile', '$animate', '$sce', -                  function($http,   $templateCache,   $anchorScroll,   $compile,   $animate,   $sce) { +var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce', +                  function($http,   $templateCache,   $anchorScroll,   $animate,   $sce) {    return {      restrict: 'ECA',      priority: 400,      terminal: true,      transclude: 'element', +    controller: angular.noop,      compile: function(element, attr) {        var srcExp = attr.ngInclude || attr.src,            onloadExp = attr.onload || '', @@ -187,6 +188,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'              $http.get(src, {cache: $templateCache}).success(function(response) {                if (thisChangeId !== changeCounter) return;                var newScope = scope.$new(); +              ctrl.template = response;                // Note: This will also link all children of ng-include that were contained in the original                // html. If that content contains controllers, ... they could pollute/change the scope. @@ -194,15 +196,14 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'                // Note: We can't remove them in the cloneAttchFn of $transclude as that                // function is called before linking the content, which would apply child                // directives to non existing elements. -              var clone = $transclude(newScope, noop); -              cleanupLastIncludeContent(); +              var clone = $transclude(newScope, function(clone) { +                cleanupLastIncludeContent(); +                $animate.enter(clone, null, $element, afterAnimation); +              });                currentScope = newScope;                currentElement = clone; -              currentElement.html(response); -              $animate.enter(currentElement, null, $element, afterAnimation); -              $compile(currentElement.contents())(currentScope);                currentScope.$emit('$includeContentLoaded');                scope.$eval(onloadExp);              }).error(function() { @@ -211,9 +212,28 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'              scope.$emit('$includeContentRequested');            } else {              cleanupLastIncludeContent(); +            ctrl.template = null;            }          });        };      }    };  }]; + +// This directive is called during the $transclude call of the first `ngInclude` directive. +// It will replace and compile the content of the element with the loaded template. +// We need this directive so that the element content is already filled when +// the link function of another directive on the same element as ngInclude +// is called. +var ngIncludeFillContentDirective = ['$compile', +  function($compile) { +    return { +      restrict: 'ECA', +      priority: -400, +      require: 'ngInclude', +      link: function(scope, $element, $attr, ctrl) { +        $element.html(ctrl.template); +        $compile($element.contents())(scope); +      } +    }; +  }]; diff --git a/test/ng/directive/ngIncludeSpec.js b/test/ng/directive/ngIncludeSpec.js index 2d115e8b..9e0a47b0 100644 --- a/test/ng/directive/ngIncludeSpec.js +++ b/test/ng/directive/ngIncludeSpec.js @@ -524,6 +524,46 @@ describe('ngInclude and transcludes', function() {      });    }); + +  it('should link directives on the same element after the content has been loaded', function() { +    var contentOnLink; +    module(function() { +      directive('test', function() { +        return { +          link: function(scope, element) { +            contentOnLink = element.text(); +          } +        }; +      }); +    }); +    inject(function($compile, $rootScope, $httpBackend) { +      $httpBackend.expectGET('include.html').respond('someContent'); +      element = $compile('<div><div ng-include="\'include.html\'" test></div>')($rootScope); +      $rootScope.$apply(); +      $httpBackend.flush(); +      expect(contentOnLink).toBe('someContent'); +    }); +  }); + +  it('should add the content to the element before compiling it', function() { +    var root; +    module(function() { +      directive('test', function() { +        return { +          link: function(scope, element) { +            root = element.parent().parent(); +          } +        }; +      }); +    }); +    inject(function($compile, $rootScope, $httpBackend) { +      $httpBackend.expectGET('include.html').respond('<span test></span>'); +      element = $compile('<div><div ng-include="\'include.html\'"></div>')($rootScope); +      $rootScope.$apply(); +      $httpBackend.flush(); +      expect(root[0]).toBe(element[0]); +    }); +  });  });  describe('ngInclude animations', function() { | 
