6

I'm using UI-router in my app and I'd like to so a simple "scrollTo" to an anchor when the URL/state changes. I don't want to load the next step from a template, or load a new controller. I'd just like several divs to be on the page already and scroll up and down between them. A simplified view of the HTML would be this.

    <div id="step1">
        <button ng-click="moveToStep2()">Continue</button>
    </div>
    <div id="step2">
        <button ng-click="moveToStep3()">Continue</button>
    </div>
    <div id="step3">
        Step 3 content
    </div>

So, when you enter the page the URL would be domain.com/booking

When you click the first button I'd like my controller code to change the URL to domain.com/#/step-2 and scroll down to the "step2" div.

Ideally, when the user hits the back button it would revert to the first URL and scroll back up to step 1.

Anybody know how to do this?

4 Answers 4

13
+50

First. You need to define the state.

.state('step1', {
    url: '/step-1'
})

Add onEnter controller (so you can $inject things).

.state('step1', {
    url: '/step-1',
    onEnter: function () {}
})

Animate (or simply scroll) to element

$('html, body').animate({
    scrollTop: $("#step1").offset().top
}, 2000);

Here the example

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

2 Comments

Can I use this on a page which has no UI-view tag though?
@jonhobbs Yep. From the documentation: The ui-view directive tells $state where to place your templates., so if you don't use templates you don't need it.
9

Using

You can do something like this:

$stateProvider.state("step1", {
  template: 'template.html',
  controller: ...,
  onEnter: function(){
      $location.hash('step1');
      $anchorScroll();
  }
});
...

Comments

1

You can listen to $locationChangeSuccess, e.g.

$rootScope.$on('$locationChangeSuccess', scrollBasedOnLocationChangeEvent);

Basic example: http://angular-ui.github.io/ui-router/site/#/api/ui.router.router.$urlRouter

2 Comments

OK, so should I just set up some states which all point to the same URL, then listen for the location change and use jqLite animate inside the listener to make this work? I was hoping that UI-router would have some way of doing this so I don't have to put scrolling code in my controller.
I wouldn't put this code in a controller either - but it looks like onEnter is the correct solution.
0

If the divs are already on the current page, just hard code the href to teh current

<div id="step1">
<a href="wizard.html#/wizard/start#step1">Continue to step 1</a>
</div>
<div id="step2">
<a href="wizard.html#/wizard/start#step2">Continue step 2</a>
</div>
<div id="step3">
    Step 3 content
</div>

<a name="#step2">STEP 2</a>

<a name="#step1">STEP 1</a>

1 Comment

I need to call a function using ng-click first because it has to make a call to my API with the booking details. also, is bypassing UI-router a good idea? I'd rather call the routers .go() method than just use window.location as I want the history to work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.