mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 07:40:22 +00:00
fix(ngView): Add template to DOM before linking other directives
The template needs to be added to the DOM before other directives at the same element as `ngView` are linked. Related to #5247.
This commit is contained in:
parent
43072e3812
commit
f8944efe70
2 changed files with 87 additions and 27 deletions
|
|
@ -1,6 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
ngRouteModule.directive('ngView', ngViewFactory);
|
||||
ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
|
|
@ -166,8 +168,8 @@ ngRouteModule.directive('ngView', ngViewFactory);
|
|||
* @description
|
||||
* Emitted every time the ngView content is reloaded.
|
||||
*/
|
||||
ngViewFactory.$inject = ['$route', '$anchorScroll', '$compile', '$controller', '$animate'];
|
||||
function ngViewFactory( $route, $anchorScroll, $compile, $controller, $animate) {
|
||||
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
|
||||
function ngViewFactory( $route, $anchorScroll, $animate) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
terminal: true,
|
||||
|
|
@ -199,6 +201,7 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
|
|||
|
||||
if (template) {
|
||||
var newScope = scope.$new();
|
||||
var current = $route.current;
|
||||
|
||||
// Note: This will also link all children of ng-view that were contained in the original
|
||||
// html. If that content contains controllers, ... they could pollute/change the scope.
|
||||
|
|
@ -206,34 +209,18 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
|
|||
// 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, angular.noop);
|
||||
clone.html(template);
|
||||
$animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
|
||||
if (angular.isDefined(autoScrollExp)
|
||||
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
||||
$anchorScroll();
|
||||
}
|
||||
var clone = $transclude(newScope, function(clone) {
|
||||
$animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
|
||||
if (angular.isDefined(autoScrollExp)
|
||||
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
||||
$anchorScroll();
|
||||
}
|
||||
});
|
||||
cleanupLastView();
|
||||
});
|
||||
|
||||
cleanupLastView();
|
||||
|
||||
var link = $compile(clone.contents()),
|
||||
current = $route.current;
|
||||
|
||||
currentScope = current.scope = newScope;
|
||||
currentElement = clone;
|
||||
|
||||
if (current.controller) {
|
||||
locals.$scope = currentScope;
|
||||
var controller = $controller(current.controller, locals);
|
||||
if (current.controllerAs) {
|
||||
currentScope[current.controllerAs] = controller;
|
||||
}
|
||||
clone.data('$ngControllerController', controller);
|
||||
clone.children().data('$ngControllerController', controller);
|
||||
}
|
||||
|
||||
link(currentScope);
|
||||
currentScope = current.scope = newScope;
|
||||
currentScope.$emit('$viewContentLoaded');
|
||||
currentScope.$eval(onloadExp);
|
||||
} else {
|
||||
|
|
@ -243,3 +230,36 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
// This directive is called during the $transclude call of the first `ngView` 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 ngView
|
||||
// is called.
|
||||
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
|
||||
function ngViewFillContentFactory($compile, $controller, $route) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
priority: -400,
|
||||
link: function(scope, $element) {
|
||||
var current = $route.current,
|
||||
locals = current.locals;
|
||||
|
||||
$element.html(locals.$template);
|
||||
|
||||
var link = $compile($element.contents());
|
||||
|
||||
if (current.controller) {
|
||||
locals.$scope = scope;
|
||||
var controller = $controller(current.controller, locals);
|
||||
if (current.controllerAs) {
|
||||
scope[current.controllerAs] = controller;
|
||||
}
|
||||
$element.data('$ngControllerController', controller);
|
||||
$element.children().data('$ngControllerController', controller);
|
||||
}
|
||||
|
||||
link(scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -582,6 +582,46 @@ describe('ngView and transcludes', function() {
|
|||
});
|
||||
|
||||
});
|
||||
|
||||
it('should link directives on the same element after the content has been loaded', function() {
|
||||
var contentOnLink;
|
||||
module(function($compileProvider, $routeProvider) {
|
||||
$routeProvider.when('/view', {template: 'someContent'});
|
||||
$compileProvider.directive('test', function() {
|
||||
return {
|
||||
link: function(scope, element) {
|
||||
contentOnLink = element.text();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function($compile, $rootScope, $location) {
|
||||
element = $compile('<div><div ng-view test></div>')($rootScope);
|
||||
$location.url('/view');
|
||||
$rootScope.$apply();
|
||||
expect(contentOnLink).toBe('someContent');
|
||||
});
|
||||
});
|
||||
|
||||
it('should add the content to the element before compiling it', function() {
|
||||
var root;
|
||||
module(function($compileProvider, $routeProvider) {
|
||||
$routeProvider.when('/view', {template: '<span test></span>'});
|
||||
$compileProvider.directive('test', function() {
|
||||
return {
|
||||
link: function(scope, element) {
|
||||
root = element.parent().parent();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function($compile, $rootScope, $location) {
|
||||
element = $compile('<div><div ng-view></div>')($rootScope);
|
||||
$location.url('/view');
|
||||
$rootScope.$apply();
|
||||
expect(root[0]).toBe(element[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ngView animations', function() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue