Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit da344da

Browse files
committed
fix(ngView): only run anchorScroll after animation is done
1 parent 6fb1915 commit da344da

File tree

2 files changed

+109
-4
lines changed

2 files changed

+109
-4
lines changed

src/ngRoute/directive/ngView.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
177177
return function(scope, $element, attr) {
178178
var currentScope,
179179
currentElement,
180+
autoScrollExp = attr.autoscroll,
180181
onloadExp = attr.onload || '';
181182

182183
scope.$on('$routeChangeSuccess', update);
@@ -201,7 +202,12 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
201202
var newScope = scope.$new();
202203
linker(newScope, function(clone) {
203204
clone.html(template);
204-
$animate.enter(clone, null, currentElement || $element);
205+
$animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
206+
if (angular.isDefined(autoScrollExp)
207+
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
208+
$anchorScroll();
209+
}
210+
});
205211

206212
cleanupLastView();
207213

@@ -224,9 +230,6 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
224230
link(currentScope);
225231
currentScope.$emit('$viewContentLoaded');
226232
currentScope.$eval(onloadExp);
227-
228-
// $anchorScroll might listen on event...
229-
$anchorScroll();
230233
});
231234
} else {
232235
cleanupLastView();

test/ngRoute/directive/ngViewSpec.js

+102
Original file line numberDiff line numberDiff line change
@@ -698,4 +698,106 @@ describe('ngView animations', function() {
698698
}
699699
});
700700
});
701+
702+
703+
describe('autoscroll', function () {
704+
var autoScrollSpy;
705+
706+
function spyOnAnchorScroll() {
707+
return function($provide, $routeProvider) {
708+
autoScrollSpy = jasmine.createSpy('$anchorScroll');
709+
$provide.value('$anchorScroll', autoScrollSpy);
710+
$routeProvider.when('/foo', {
711+
controller: angular.noop,
712+
template: '<div></div>'
713+
});
714+
};
715+
}
716+
717+
function spyOnAnimateEnter() {
718+
return function($animate) {
719+
spyOn($animate, 'enter').andCallThrough();
720+
};
721+
}
722+
723+
function compileAndLink(tpl) {
724+
return function($compile, $rootScope, $location) {
725+
element = $compile(tpl)($rootScope);
726+
};
727+
}
728+
729+
beforeEach(module(spyOnAnchorScroll(), 'mock.animate'));
730+
beforeEach(inject(spyOnAnimateEnter()));
731+
732+
it('should call $anchorScroll if autoscroll attribute is present', inject(
733+
compileAndLink('<div><ng:view autoscroll></ng:view></div>'),
734+
function($rootScope, $animate, $timeout, $location) {
735+
736+
$location.path('/foo');
737+
$rootScope.$digest();
738+
$animate.flushNext('enter');
739+
$timeout.flush();
740+
741+
expect(autoScrollSpy).toHaveBeenCalledOnce();
742+
}));
743+
744+
745+
it('should call $anchorScroll if autoscroll evaluates to true', inject(
746+
compileAndLink('<div><ng:view src="tpl" autoscroll="value"></ng:view></div>'),
747+
function($rootScope, $animate, $timeout, $location) {
748+
749+
$rootScope.value = true;
750+
$location.path('/foo');
751+
$rootScope.$digest();
752+
$animate.flushNext('enter');
753+
$timeout.flush();
754+
755+
expect(autoScrollSpy).toHaveBeenCalledOnce();
756+
}));
757+
758+
759+
it('should not call $anchorScroll if autoscroll attribute is not present', inject(
760+
compileAndLink('<div><ng:view></ng:view></div>'),
761+
function($rootScope, $location, $animate, $timeout) {
762+
763+
$location.path('/foo');
764+
$rootScope.$digest();
765+
$animate.flushNext('enter');
766+
$timeout.flush();
767+
768+
expect(autoScrollSpy).not.toHaveBeenCalled();
769+
}));
770+
771+
772+
it('should not call $anchorScroll if autoscroll evaluates to false', inject(
773+
compileAndLink('<div><ng:view autoscroll="value"></ng:view></div>'),
774+
function($rootScope, $location, $animate, $timeout) {
775+
776+
$rootScope.value = false;
777+
$location.path('/foo');
778+
$rootScope.$digest();
779+
$animate.flushNext('enter');
780+
$timeout.flush();
781+
782+
expect(autoScrollSpy).not.toHaveBeenCalled();
783+
}));
784+
785+
786+
it('should only call $anchorScroll after the "enter" animation completes', inject(
787+
compileAndLink('<div><ng:view autoscroll></ng:view></div>'),
788+
function($rootScope, $location, $animate, $timeout) {
789+
$location.path('/foo');
790+
791+
expect($animate.enter).not.toHaveBeenCalled();
792+
$rootScope.$digest();
793+
794+
expect(autoScrollSpy).not.toHaveBeenCalled();
795+
796+
$animate.flushNext('enter');
797+
$timeout.flush();
798+
799+
expect($animate.enter).toHaveBeenCalledOnce();
800+
expect(autoScrollSpy).toHaveBeenCalledOnce();
801+
}));
802+
});
701803
});

0 commit comments

Comments
 (0)