I'm very close to finishing up my page, and I ran into this odd bug.
When I use ng-include, the pages load fine, but they resume scrolling from the previous position, so they don't start at the top with every click.
I resorted to using anchor scroll, but it doesn't work properly. I have to click the link again, for it to load the contents, and if I click the same link again, it offsets the page to some weird position.
This is my code in the controller:
$scope.toPage = function (index, id) {
$scope.missiveIndex = index;
$scope.contentsDown();
$location.hash(id);
};
and this is the HTML part:
<article id="{{articles.ids}}" class="stories-anim" ng-repeat="articles in stories" ng-hide="!isMissiveSlideIndex($index)" ng-include="articles.content" [autoscroll]>
</article>
the id is passed in via ng-click="ng-click="toPage($index, button.ids);"
is there a way to put the location.hash in the [onload] expression and autoscroll that way?
thanks
Probably the anchor scroll didn't work because the content of the page was not fully loaded when it was called.
You can solve that by using a timeout.
$timeout(function() {
$anchorScroll();
},500);
Related
I have a collapsible sidebar navigation, and any time users click a link on it, I have the sidebar hide automatically. I achieve this in the run method by using the following code:
app.run(function($rootScope) {
$rootScope.$on('$routeChangeSuccess', function () {
$rootScope.closeNavigation();
})
});
Where app is my Angularjs module.
The problem is that it gets a little unintuitive to use, when you click a link in the navigation for the page you're already on, and then nothing happens. What I would like is to have the sidebar close anyway, so that the users still get focus on the content, even if it's the same content.
But Angularjs doesn't execute the $routeChangeSucess event, if there is no route change happening. So what can I use instead?
You simply need to use ng-show = isPanelVisible and ng-click = closePanel() on the html sidepanel tag (e.g. a <div>).
Then, define $scope.closePanel() in the controller associated to the actual view. For instance
$scope.closePanel = function() {
$scope.isPanelVisible = false;
}
See an example here. Code is here. Note that it doesn't use ng-show, but the behaviour is the same.
On the click of a button i want the page to scroll a particular div bottom.
The 1st time i click, the page is going to the very top and the initial url http://localhost:8000 becomes http://localhost:8000/#/bottom(why is it not going to the div i mentioned).
The 2nd time i click the button, the url becomes
http://localhost:8000/#/bottom#bottom and it goes to the div bottom(which is what i want).
How do i deal with this ?
code snippet
$location.hash('bottom');
$anchorScroll();
Thanks in advance
Do ask for more explanation if required . . .
I don't know if you still need help, but have you checked this question?
Anyway, I also use one button to do a anchor scroll:
<button ng-click="app.gotoAnchor('destination')">GO!</button>
(...)
<div id="destination" style="height:1px;"></div>
And I just used a combination of AngularJS documentation examples and the SO question I mentioned before, to make this function:
function gotoAnchor(anchor){
if ($location.hash() !== newHash) {
// set the $location.hash to `newHash` and
// $anchorScroll will automatically scroll to it
$timeout(function() {
$location.hash(anchor);
});
} else {
// call $anchorScroll() explicitly,
// since $location.hash hasn't changed
$anchorScroll();
}
}
Being the $timeout call the one that made this work better.
Hope this helps.
BOTTOM
<div style="height:700px"> this is boby </div>
JOIN NOW!
On the first hit to a page I want to send a fully rendered page back to the user. This works fine if javascript is disabled, but if javascript is enabled then angular-ui-router looks up the state and renders into ui-view on top of the existing content. Is there a way to disable this on the first page load somehow?
See this issue: https://github.com/angular-ui/ui-router/issues/1807 which suggests using $urlRouterProvider.deferIntercept(), but I can't find much documentation about using it and not sure how to intercept the first page load.
There's two parts: firstly you need to disable the router from kicking in on the first page load. This can be done like so:
app.config(function($httpProvider, $urlRouterProvider) {
// On the first page load disable ui-router so that
// our server rendered page is not reloaded based on the window location.
$urlRouterProvider.deferIntercept();
});
Secondly we need to set up the ui-view correctly: Dumping the server-rendered markup inside the ui-view causes issues weird behaviour with the first controller being run twice (see https://github.com/angular-ui/ui-router/issues/1807), so we'll add our server rendered markup just after the ui-view div and hide the ui-view until there's a navigation event.
<div ng-controller="PropertyDetailCtrl">
<div class="ng-cloak" ng-show="!isFirstPageLoad" ui-view></div>
<div ng-show="isFirstPageLoad">
(server rendered markup goes here)
</div>
</div>
Now we need to set isFirstPageLoad in the $scope:
app.controller('PropertyDetailCtrl', function loader($rootScope, $scope) {
$scope.isFirstPageLoad = true;
$rootScope.$on('$viewContentLoading', function(event, viewConfig) {
$scope.isFirstPageLoad = false;
});
});
We've used ng-cloak to make sure that the page behaves perfectly if javascript is disabled, so now we've got a fully server side rendered first page load with all subsequent navigation handled by ui-router.
This question already has answers here:
Changing route doesn't scroll to top in the new page
(18 answers)
Closed 8 years ago.
For example:
A user scrolls down on view A;
Then the user clicks on a link, which takes the user to view B;
The view is changes,
but the user's vertical location remains lthe same, and must scroll manually to the top of the screen.
Is it an angular bug?
I wrote a small workaround that uses jquery to scroll to the top; but I don't find the correct event to bind it to.
edit after seeing the comment:
How and WHEN do i pull myself to the top? i'm using jquery but the $viewContentLoaded event is too soon (the method runs, but the page doesn't scroll at that time)
The solution is to add autoscroll="true" to your ngView element:
<div class="ng-view" autoscroll="true"></div>
https://docs.angularjs.org/api/ngRoute/directive/ngView
Angular doesn't automatically scroll to the top when loading a new view, it just keeps the current scroll position.
Here is the workaround I use:
myApp.run(function($rootScope, $window) {
$rootScope.$on('$routeChangeSuccess', function () {
var interval = setInterval(function(){
if (document.readyState == 'complete') {
$window.scrollTo(0, 0);
clearInterval(interval);
}
}, 200);
});
});
Put it in your bootstrap (usually called app.js).
It's a pure javascript solution (it's always better not to use jQuery if it's easy).
Explanation: The script checks every 200ms if the new DOM is fully loaded and then scrolls to the top and stops checking. I tried without this 200ms loop and it sometimes failed to scroll because the page was just not completely displayed.
It seems that you understand why the problem is happening based on #jarrodek's comment.
As for a solution, you could either follow #TongShen's solution of wrapping your function in a $timeout or you can put the function call within the partial that you're loading.
<!-- New partial-->
<div ng-init="scrollToTop()">
</div>
If you view change is fired after a click event, you could also put the function call on that element. Just comes down to timing though. Just depends on how things are set up.
I have a fixed top menu in Angular but when I try to switch page (within the app) the browser windows is not scrolling up.
I try to do this in my controller (this code is loaded every time i switch page within the app):
$('body').scroll();
window.scrollTo(0, 0);
$("html, body").animate({ scrollTop: 0 }, 100);
None of which is working.
Is there any trick that i am missing?
I tried this as well:
$location.hash('#top');
// call $anchorScroll()
$anchorScroll();
but without success
First of all, you should never attach DOM events or modify DOM from controller. You can use directives for that.
As per you question - AngularJS has an event called '$routeChangeSuccess'.
You can attach handler to this event with $scope.$on('$routeChangeSuccess', function () {...}) and run scrolling code inside.