'use strict'; /** * @ngdoc directive * @name ng.directive:ngInclude * @restrict ECA * * @description * Fetches, compiles and includes an external HTML fragment. * * By default, the template URL is restricted to the same domain and protocol as the * application document. This is done by calling {@link ng.$sce#getTrustedResourceUrl * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or * {@link ng.$sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link * ng.$sce Strict Contextual Escaping}. * * In addition, the browser's * {@link https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest * Same Origin Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing * (CORS)} policy may further restrict whether the template is successfully loaded. * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://` * access on some browsers. * * @animations * enter - animation is used to bring new content into the browser. * leave - animation is used to animate existing content away. * * The enter and leave animation occur concurrently. * * @scope * @priority 400 * * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant, * make sure you wrap it in quotes, e.g. `src="'myPartialTemplate.html'"`. * @param {string=} onload Expression to evaluate when a new partial is loaded. * * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll * $anchorScroll} to scroll the viewport after the content is loaded. * * - If the attribute is not set, disable scrolling. * - If the attribute is set without value, enable scrolling. * - Otherwise enable scrolling only if the expression evaluates to truthy value. * * @example
url of the template: {{template.url}}
function Ctrl($scope) { $scope.templates = [ { name: 'template1.html', url: 'template1.html'} , { name: 'template2.html', url: 'template2.html'} ]; $scope.template = $scope.templates[0]; } Content of template1.html Content of template2.html .example-animate-container { position:relative; background:white; border:1px solid black; height:40px; overflow:hidden; } .example-animate-container > div { padding:10px; } .include-example.ng-enter, .include-example.ng-leave { -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; position:absolute; top:0; left:0; right:0; bottom:0; display:block; padding:10px; } .include-example.ng-enter { top:-50px; } .include-example.ng-enter.ng-enter-active { top:0; } .include-example.ng-leave { top:0; } .include-example.ng-leave.ng-leave-active { top:50px; } it('should load template1.html', function() { expect(element('.doc-example-live [ng-include]').text()). toMatch(/Content of template1.html/); }); it('should load template2.html', function() { select('template').option('1'); expect(element('.doc-example-live [ng-include]').text()). toMatch(/Content of template2.html/); }); it('should change to blank', function() { select('template').option(''); expect(element('.doc-example-live [ng-include]')).toBe(undefined); });
*/ /** * @ngdoc event * @name ng.directive:ngInclude#$includeContentRequested * @eventOf ng.directive:ngInclude * @eventType emit on the scope ngInclude was declared in * @description * Emitted every time the ngInclude content is requested. */ /** * @ngdoc event * @name ng.directive:ngInclude#$includeContentLoaded * @eventOf ng.directive:ngInclude * @eventType emit on the current ngInclude scope * @description * Emitted every time the ngInclude content is reloaded. */ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile', '$animate', '$sce', function($http, $templateCache, $anchorScroll, $compile, $animate, $sce) { return { restrict: 'ECA', priority: 400, terminal: true, transclude: 'element', compile: function(element, attr, transclusion) { var srcExp = attr.ngInclude || attr.src, onloadExp = attr.onload || '', autoScrollExp = attr.autoscroll; return function(scope, $element) { var changeCounter = 0, currentScope, currentElement; var cleanupLastIncludeContent = function() { if (currentScope) { currentScope.$destroy(); currentScope = null; } if(currentElement) { $animate.leave(currentElement); currentElement = null; } }; scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) { var thisChangeId = ++changeCounter; if (src) { $http.get(src, {cache: $templateCache}).success(function(response) { if (thisChangeId !== changeCounter) return; var newScope = scope.$new(); transclusion(newScope, function(clone) { cleanupLastIncludeContent(); currentScope = newScope; currentElement = clone; currentElement.html(response); $animate.enter(currentElement, null, $element); $compile(currentElement.contents())(currentScope); if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { $anchorScroll(); } currentScope.$emit('$includeContentLoaded'); scope.$eval(onloadExp); }); }).error(function() { if (thisChangeId === changeCounter) cleanupLastIncludeContent(); }); scope.$emit('$includeContentRequested'); } else { cleanupLastIncludeContent(); } }); }; } }; }];