Skip to content

Commit

Permalink
fix(ngInclude): only run anchorScroll after animation is done
Browse files Browse the repository at this point in the history
We need to wait until animations have added the content to the document before
trying to `autoscroll` to anchors that may have been inserted.

Fixes angular#4723
  • Loading branch information
petebacondarwin authored and jamesdaily committed Jan 27, 2014
1 parent 47637ec commit 39c5c0f
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 30 deletions.
12 changes: 6 additions & 6 deletions src/ng/directive/ngInclude.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
};

scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
var afterAnimation = function() {
if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
$anchorScroll();
}
};
var thisChangeId = ++changeCounter;

if (src) {
Expand All @@ -190,13 +195,8 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
currentElement = clone;

currentElement.html(response);
$animate.enter(currentElement, null, $element);
$animate.enter(currentElement, null, $element, afterAnimation);
$compile(currentElement.contents())(currentScope);

if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
$anchorScroll();
}

currentScope.$emit('$includeContentLoaded');
scope.$eval(onloadExp);
});
Expand Down
110 changes: 86 additions & 24 deletions test/ng/directive/ngIncludeSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ describe('ngInclude', function() {
}));


describe('autoscoll', function() {
describe('autoscroll', function() {
var autoScrollSpy;

function spyOnAnchorScroll() {
Expand All @@ -328,52 +328,114 @@ describe('ngInclude', function() {
};
}

function changeTplAndValueTo(template, value) {
return function($rootScope, $browser) {
$rootScope.$apply(function() {
$rootScope.tpl = template;
$rootScope.value = value;
});
};
}

beforeEach(module(spyOnAnchorScroll()));
beforeEach(module(spyOnAnchorScroll(), 'mock.animate'));
beforeEach(inject(
putIntoCache('template.html', 'CONTENT'),
putIntoCache('another.html', 'CONTENT')));


it('should call $anchorScroll if autoscroll attribute is present', inject(
compileAndLink('<div><ng:include src="tpl" autoscroll></ng:include></div>'),
changeTplAndValueTo('template.html'), function() {
function($rootScope, $animate, $timeout) {

$rootScope.$apply(function () {
$rootScope.tpl = 'template.html';
});

expect(autoScrollSpy).not.toHaveBeenCalled();
$animate.flushNext('enter');
$timeout.flush();

expect(autoScrollSpy).toHaveBeenCalledOnce();
}));


it('should call $anchorScroll if autoscroll evaluates to true', inject(
compileAndLink('<div><ng:include src="tpl" autoscroll="value"></ng:include></div>'),
changeTplAndValueTo('template.html', true),
changeTplAndValueTo('another.html', 'some-string'),
changeTplAndValueTo('template.html', 100), function() {
it('should call $anchorScroll if autoscroll evaluates to true',
inject(function($rootScope, $compile, $animate, $timeout) {

element = $compile('<div><ng:include src="tpl" autoscroll="value"></ng:include></div>')($rootScope);

$rootScope.$apply(function () {
$rootScope.tpl = 'template.html';
$rootScope.value = true;
});

$animate.flushNext('enter');
$timeout.flush();

$rootScope.$apply(function () {
$rootScope.tpl = 'another.html';
$rootScope.value = 'some-string';
});

$animate.flushNext('leave');
$animate.flushNext('enter');
$timeout.flush();

$rootScope.$apply(function() {
$rootScope.tpl = 'template.html';
$rootScope.value = 100;
});

$animate.flushNext('leave');
$animate.flushNext('enter');
$timeout.flush();

expect(autoScrollSpy).toHaveBeenCalled();
expect(autoScrollSpy.callCount).toBe(3);
}));


it('should not call $anchorScroll if autoscroll attribute is not present', inject(
compileAndLink('<div><ng:include src="tpl"></ng:include></div>'),
changeTplAndValueTo('template.html'), function() {
function($rootScope, $animate, $timeout) {

$rootScope.$apply(function () {
$rootScope.tpl = 'template.html';
});

$animate.flushNext('enter');
$timeout.flush();
expect(autoScrollSpy).not.toHaveBeenCalled();
}));


it('should not call $anchorScroll if autoscroll evaluates to false', inject(
compileAndLink('<div><ng:include src="tpl" autoscroll="value"></ng:include></div>'),
changeTplAndValueTo('template.html', false),
changeTplAndValueTo('template.html', undefined),
changeTplAndValueTo('template.html', null), function() {
it('should not call $anchorScroll if autoscroll evaluates to false',
inject(function($rootScope, $compile, $animate, $timeout) {

element = $compile('<div><ng:include src="tpl" autoscroll="value"></ng:include></div>')($rootScope);

$rootScope.$apply(function () {
$rootScope.tpl = 'template.html';
$rootScope.value = false;
});

$animate.flushNext('enter');
$timeout.flush();

$rootScope.$apply(function () {
$rootScope.tpl = 'template.html';
$rootScope.value = undefined;
});

$rootScope.$apply(function () {
$rootScope.tpl = 'template.html';
$rootScope.value = null;
});

expect(autoScrollSpy).not.toHaveBeenCalled();
}));

it('should only call $anchorScroll after the "enter" animation completes', inject(
compileAndLink('<div><ng:include src="tpl" autoscroll></ng:include></div>'),
function($rootScope, $animate, $timeout) {
expect(autoScrollSpy).not.toHaveBeenCalled();

$rootScope.$apply("tpl = 'template.html'");
$animate.flushNext('enter');
$timeout.flush();

expect(autoScrollSpy).toHaveBeenCalledOnce();
}));
});
});

Expand Down

0 comments on commit 39c5c0f

Please sign in to comment.