I don't see any other solution than deferring the invocation of scrollTop()
when using ng-show
. You have to wait until the changes in your model are reflected in the DOM, so the elements become visible. The reason why they do not appear instantly is the scope life cycle. ng-show
internally uses a watch listener that is only fired when the $digest()
function of the scope is called after the execution of the complete code in your click handler.
See http://docs.angularjs.org/api/ng.$rootScope.Scope for a more detailed explanation of the scope life cycle.
Usually it should not be a problem to use a timeout that executes after this event with no delay like this:
setTimeout(function() {
$(window).scrollTop(50);
}, 0);
Alternative solution without timeout:
However, if you want to avoid the timeout event (the execution of which may be preceded by other events in the event queue) and make sure that scrolling happens within the click event handler. You can do the following in your controller:
$scope.$watch('itemsVisible', function(newValue, oldValue) {
if (newValue === true && oldValue === false) {
$scope.$evalAsync(function() {
$(window).scrollTop(50);
});
}
});
The watch listener fires within the same invocation of $digest()
as the watch listener registered by the ng-show
directive. The function passed to $evalAsync()
is executed by angular right after all watch listeners are processed, so the elements have been already made visible by the ng-show
directive.