Angular4 - scroll to anchor

I am trying to do a simple scroll to an anchor element on the same page. Basically, the person clicks the "Try" button and he scrolls down to the area below the page with the id "login". Now he works with basic id="login"

and <a href="#login"></a>

, but he goes to this section. Ideally, I would like it to scroll there. If I am using Angular4, is there a built-in way to do this or which is the simplest way? Thank!

Whole template ... (component still empty)

<div id="image-header">
    <div id="intro">
        <h1 class="text-center">Welcome to ThinkPlan</h1>
        <h3 class="text-center">Planning your way</h3>
        <a class="btn btn-outline-primary" href="#login" id="view">Try It</a> <!-- Where the user clicks to scroll -->
    </div>
</div>
<div class="container" id="info">
    <div class="row">
        <div class="col-md-12">
             <div class="space" id="login"></div> <!-- The place to scroll to -->
                <h1 class="text-center">ThinkPlan</h1>
                <form  class="form-horizontal">
                    <fieldset>
                        <legend>Login</legend>
                        <div class="form-group">
                            <label for="inputEmail" class="col-lg-2 control-label">Email</label>
                            <div class="col-lg-10">
                                <input type="text" class="form-control" id="inputEmail" placeholder="Email">
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="inputPassword" class="col-lg-2 control-label">Password</label>
                            <div class="col-lg-10">
                                <input type="password" class="form-control" id="inputPassword" placeholder="Password"> 
                            </div>
                        </div>
                        <div class="form-group" id="log-btn">
                            <div class="col-lg-10 col-lg-offset-2">
                                <button routerLink="/plan" type="submit" class="btn btn-outline-primary">Login</button>
                            </div>
                        </div>
                        <p class="lead text-center">New here? <a routerLink="signup">Sign up.</a></p>
                    </fieldset>
                </form>
        </div>
    </div>
</div>

      

+19


source to share


5 answers


I think this is a simpler solution:

In your HTML:

<a [routerLink]="['/']" fragment="login"></a>

      



In typescript:

ngOnInit() {
 this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
}

ngAfterViewChecked(): void {
  try {
      if(this.fragment) {
          document.querySelector('#' + this.fragment).scrollIntoView();
      }
  } catch (e) { }
}

      

+17


source


Auto scroll

Starting with Angular v6, there is a new option anchorScrolling

for RouterModule

. You can install it in the import module:

imports: [
  ...,
  RouterModule.forRoot(routes, {anchorScrolling: 'enabled'})

      

Angular will automatically scroll to the element with the ID of the given fragment.

⚠️ However, this does not work when data is loaded asynchronously, see this Github issue . ⚠️




Manual scrolling

With RouterModule

smooth scrolling
is not yet possible, but you can do it manually:

1) Get your target, for example with ViewChild

:

@ViewChild('pageInfo') pageInfo: ElementRef; 

      

2) Call scrollIntoView

to nativeElement

:

const targetElement = this.pageInfo.nativeElement
targetElement.scrollIntoView({behavior: "smooth"})

      

+13


source


With Angular 4, you might have a problem linking to the same page.

I decided to use this way

ng2-page-scroll

install

npm install ng2-page-scroll --save

      

import to your app.module.ts

import {Ng2PageScrollModule} from 'ng2-page-scroll';

@NgModule({
    imports: [
        /* Other imports here */
        Ng2PageScrollModule
        ]
})
export class AppModule {
}

      

check it in html component

<a pageScroll href="#test">Testing</a>
<div id="test">

      

+3


source


AfterViewCheck()

will be called every time it fires ChangeDetection

, so this is a bad solution.

Use AfterViewInit()

as

public ngAfterViewInit(): void {
  this.subscription = this.route.fragment
    .subscribe(fragment => {
        const targetElement = this.document.querySelector('#' + fragment);
        if (fragment && targetElement) {
            targetElement.scrollIntoView();
        } else {
            window.scrollTo(0, 0);
        }
    });
}
public ngOnDestroy(): void {
    this.subscription.unsubscribe();
}

      

+2


source


This is a more detailed example that can be added to Sarah Dubois's answer above.

Import of router modules.

import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';

constructor(private route:ActivatedRoute, 
            private router:Router) {

  router.events.subscribe(event => {
    if (event instanceof NavigationEnd) {    
      if (event.url) {
        this.route.fragment.subscribe(fragment => this.fragment = fragment);
      }
    }
  });

}

ngAfterViewChecked(): void {

  try {
    if(this.fragment != null) {
     document.querySelector("a[name="+this.fragment+"]").scrollIntoView();
    }
  } catch (e) {
    //console.log(e, 'error');
  }

}

      

I love using the querySelector which will give you a lot of options on which element you want to jump to. https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

This works with Angular 8 :)

0


source







All Articles