23

I need to set an ng-click event so that that it loads a new page, and then, once the page has loaded, scrolls to an anchor point on the page. I've tried every solution proposed on this SO post but I can't get it to work correctly.

Most of those solutions center around scrolling to an anchor on a page that's already loaded. I need the scroll to occur after a new page has loaded.

Here is my view code:

<div class="see-jobs-btn" ng-click="$event.stopPropagation();goToResultJobs(r)">See Jobs</div>

This represents a button inside a 'profile card'. When the user clicks on the card, it takes them to a profile page. However, when they click the button, it needs to take them to the #jobs portion of that profile page (hence the $stopPropogation() before the goToResultJobs(r) in the code).

Here is what my goToResultJobs method looks like.

$scope.goToResultJobs = function(result) {
    var profileUrl = result.slug;
    window.location = profileUrl;
};

I've tried using $anchorScroll and just hardcoding in the anchor into the profileUrl, but neither one works. I'm fairly new to Angular, so I don't know what I'm missing here.

UPDATE 1: Trying to use $timeout

Here is my goToResultJobs method within my ResultsCtrl that is triggered when the user clicks the button:

$scope.goToResultJobs = function(result) {
    var url = window.location + result.slug + '#jobs';
    location.replace(url);
};

That loads the /name#jobs path, which calls the ProfileCtrl below:

app.controller('ProfileCtrl', ['$scope', '$http', '$timeout', '$location', '$anchorScroll',
function($scope, $http, $timeout, $location, $anchorScroll) {
    if(window.location.hash) {
        $timeout(function() {
            console.log('TEST');
            // $location.hash('jobs');
            // $location.hash('jobs');
            $anchorScroll();
        }, 1000);
    };
}]);

This setup seems to work, as TEST only appears in the console when the jobs button is clicked, but not when the user just clicks on the profile. The problem I'm now facing is that the page starts loading, and the path in the url bar changes to /name#jobs, but before the page finishes loading, jobs is stripped from the url. Therefore, when $anchorScroll() is called, there is no anchor tag in the hash to scroll to.

7
  • 1
    Have you tried using $timeout($anchorScroll())? Commented May 14, 2015 at 19:59
  • Try anchorscroll Commented May 14, 2015 at 20:01
  • I tried using $timeout but it doesn't seem to fire. I inserted a console.log statement, but 'TEST' never appears in the console. See my question above for updated code: Commented May 14, 2015 at 21:09
  • Yes, because you navigate away from the page then try and make a timeout, which is gone as the page has changed. Try letting the $timeout just hang out so it's executed when it's loaded. The hash should already be in the URL. Commented May 14, 2015 at 21:17
  • Where should $timeout be in my Angular code then? There is no controller for the page that is being loaded, only for the page that lists all the profile cards. Commented May 14, 2015 at 21:23

6 Answers 6

19

So as pointed out, the $anchorScroll has to occur after the page has been rendered, otherwise the anchor doesn't exist. This can be achieved using $timeout().

$timeout(function() {
  $anchorScroll('myAnchor');
});

You can see this plunkr. Make sure to view it in pop-out mode (the little blue button in the upper right corner of the output screen).

Sign up to request clarification or add additional context in comments.

9 Comments

I moved this to just inside my controller (same as in the plunkr), but now it doesn't fire at all.
Are you getting any errors in your console? The only way the code in that block wouldn't get executed is if you didn't inject $timeout.
I'll note that I am having trouble with the $location.hash version. I see in your update you dropped the tag from the $anchorScroll, which was the only way I could get it to work in the plunkr (granted, it is plunkr).
A further note, maybe you actually have to wait: $timeout(function() {...}, 500);
So I decided to create a new controller for my profile view that just has the $timeout function in it. Now the function fires when the page finishes loading, but it doesn't work like I intended. I have it set up so that when you click on the profile card, it sends you to /name#jobs, but for some reason, before the page finishes loading, the path chances from that to /name# and there is no scrolling. I'm trying to figure out why jobs is being stripped out of the url.
|
4

Holy moly, this can be accomplished by simply adding autoscroll="true" to your template:

<div autoscroll="true" data-ng-include='"/templates/partials/layout/text-column.html"'></div>

Documentation

1 Comment

incredible, absolutely incredible.
0

In my case using fragment in Router did not work. ViewportScroller did not work either. Even if they did - I'd prefer to keep URL clean. So, this is what I used:

(document.querySelector('.router-wrapper') as HTMLElement)?.scrollIntoView();

Comments

0

How to enable Anchor Scrolling of Angular Router and their problems

https://quandh19.medium.com/how-to-enable-anchor-scrolling-of-angular-router-in-the-right-way-42e9b19657b5

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollPositionRestoration: 'enabled',
      anchorScrolling: 'enabled',
      //scrollOffset: [0, 64] // [x, y] takes into account your header
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

Working scrolling in Angular: https://stackblitz.com/edit/solution-anchor-scrolling?file=src%2Fapp%2Fproduct%2Fproduct.component.ts

Comments

-1

Maybe you can use native Javascript's Element.scrollIntoView() after the page has been loaded?

2 Comments

The key here is whatever scroll technique is used has to happen after page load. Even a small $timeout should work.
It is better to not answer a question with a question.
-1

Try:

angular.module('anchorScrollExample', [])
.controller('ScrollController', ['$scope', '$location', '$anchorScroll',
  function ($scope, $location, $anchorScroll) {
      $scope.gotoBottom = function() {
      // set the location.hash to the id of
      // the element you wish to scroll to.
      $location.hash('bottom');

      $anchorScroll();
    };
}]);

'bottom' here is the id of your html element to which you want to scroll to.

Documentation here: https://docs.angularjs.org/api/ng/service/$anchorScroll

1 Comment

This was suggested in the link I posted with my question. This doesn't work because $anchorScroll needs to fire AFTER the page loads.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.