Using HTML anchor link fragment in Angular 6
Asked Answered
A

8

54

I am working with an Angular 6 project in which I have disabled/removed hash-location-strategy which removes # from URL.

due to this change the link having:

<li routerLinkActive="active">
   <a [routerLink]="['/settings']">Contact Settings</a>
   <ul class="child-link-sub">
      <li>
         <a href="#contactTypes">Contact Types</a>
      </li>
   </ul>
</li>

is no more working it just skips the current components URL and puts #contactTypes after localhost.

I found this github issue which should solve the issue using

<a [routerLink]="['/settings/']" fragment="contactTypes" >Contact Types</a>

which puts #contactTypes at the end of the URL but it doesn't scroll to the top of the browser.

Source: https://github.com/angular/angular/issues/6595

Agni answered 13/6, 2018 at 11:48 Comment(0)
Y
63

Angular 6.1 comes with an option called anchorScrolling that lives in router module's ExtraOptions. As the anchorScrolling definition says:

Configures if the router should scroll to the element when the url has a fragment.

'disabled' -- does nothing (default).

'enabled' -- scrolls to the element. This option will be the default in the future.

Anchor scrolling does not happen on 'popstate'. Instead, we restore the position that we stored or scroll to the top.

You can use it like that:

const routerOptions: ExtraOptions = {
  useHash: false,
  anchorScrolling: 'enabled',
  // ...any other options you'd like to use
};

// then just import your RouterModule with these options

RouterModule.forRoot(MY_APP_ROUTES, routerOptions)
Yeoman answered 9/10, 2018 at 15:41 Comment(9)
Thanks for this answer. What I missed was that you have to use routerLink="./" fragment="anchorName" you can not use href="#anchorName"Verecund
Also, this only works on the first click. Does not work on the 2nd.Mucker
For this to work on the 2nd click, you need to add onSameUrlNavigation: 'reload' option in the routerOptions.Alveolus
This is how it should be implemented.Mundell
To get this solution to work I had to also add angular.io/api/router/ExtraOptions#scrollPositionRestorationLibove
Please note that this answer was based on Angular 6.1 and may not apply to current Angular version and beyond.Yeoman
^^^ Confirmed, this does work in Angular 11 too. All options mentioned above work too, i.e. anchorScrolling: 'enabled', onSameUrlNavigation: 'reload', scrollPositionRestoration: 'enabled'.Bertero
Just wondering, how to make this work on page load? anchorScrolling doesn't work automatically then, e.g. if I open my-ng-app.com/route#section-1 in a new browser directly, it does not take me to "section-1". Probably there should be a setting or manual way of doing this?Bertero
Is there a solution with HashLocationStrategy (useHash)? It's a conflict. I think you can either use one or the other. With useHash you cannot use <a href="#foo">, results in 404. It's because the hash feature is already in use by Angular Router (e.g. the URL looks like http://localhost:4200/#/). Is there a solution or should I scroll with JavaScript? :( We cannot disable hash routing.Schade
C
31

I was looking for a similar solution and tried to use the ngx-scroll-to package and found that its not working in latest version of angular so decided to look into other option and found that we can use scrollIntoView

HTML code :

<button (click)="scrollToElement(target)"></button>
<div #target>Your target</div>

Ts code :

  scrollToElement($element): void {
    console.log($element);
    $element.scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});
  }
Clyde answered 18/7, 2018 at 10:51 Comment(4)
Thanks, your answer is absolute good and easy to understand with simple and short codeAccepter
can you provide for dynamic linking? There are other answers for this purpose but code is not simpleAccepter
This is not ideal, because it does not provide the user with a link that they can share with others, such as "example.org/help#installing".Etter
@Etter Yes , "This is not ideal" right now, but that feature achorScrolling was not available when i answered the question. since angular 6.1 was released later .This solution may be helpful for those who work in older version of angular . Its great that solutions are evolving with every new version of angularClyde
M
15

This worked for me (I'm using Angular 12.1.3):

On the HTML template:

<a (click)="scrollTo('anchorId')">Scroll to another position</a>

Pass the id of the element you want to scroll to (without the hashtag symbol #) to the function.

Then, on Typescript, use .scrollIntoView to make the browser scroll to the position of that element.

scrollTo(element: any): void {
  (document.getElementById(element) as HTMLElement).scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});
}
Mediate answered 30/12, 2021 at 17:49 Comment(2)
In the HTML template: <div id="anchorId">Shalna
also works on v17.0.8Frequency
B
8

For accessibility reasons I had to a link at the beginning of the document to provide direct access to the content to user using a screen reader, skipping that way parts of the page repeating from page to page.

As I needed the link to stay focusable (preferably keeping the href attribute), as I was actually outside the app-root or any component (still solution works inside a component), to do that I used simple good old fashion html and javascript :

<a href="./#content"
     onclick="event.preventDefault(); location.hash='content';"
     class="content-shortcut"
     title="Access page content directly"
     i18n-title
     aria-label="Access page content directly"
     i18n-label>Access page content directly</a>
  <style>
    .content-shortcut {
      position: absolute;
      opacity: 0;
      height: 0px;
      font-size: 1px;
    }

    .content-shortcut:focus,
    .content-shortcut:active {
      position: relative;
      opacity: 1;
      height: auto;
      font-size: 1em;
      display: block;
      color: black;
      background: white;
    }

  </style>
Bechuanaland answered 15/8, 2019 at 15:38 Comment(2)
this is what i have to do as well, thanks for the postUlises
The best solution for meeting WCAG requirement to skip main navigation. Very simple and elegant. Thanks!Bloomer
U
4

This is for Angular 9, but, I am sure the community will benefit this,

You can use Location in the @angular/common to get the current path.

Let's say you have the following element with an id to focus

<div id="bring-me-to-the-focus">

I am only showing extracted code blocks here.

import { Location } from '@angular/common';

constructor(private location: Location) { }

this.location.path() + '#bring-me-to-the-focus'; 

I am sure this will help someone :)

Cheers.

Uncompromising answered 2/7, 2020 at 21:4 Comment(1)
I don't think this is necessary since router provide this feature with anchorScrolling and onSameUrlNavigationRevue
G
3

As pointed out by Nitin Avula in a comment, using routerLink for a hash anchor only works if you are navigating to a different route or have onSameUrlNavigation enabled in your router config.

A way to get round this is to get rid of routerLink and instead use this.router.navigate in your *.component.ts file with the fragment parameter:

HTML -

<a (click)="scrollToContactTypes()">Contact Types</a>

TypeScript -

constructor(private router: Router) { }

scrollToContactTypes() {
    this.router.onSameUrlNavigation = "reload";
    this.router.navigate(["/settings"], { fragment: "contactTypes" }).finally(() => {
        this.router.onSameUrlNavigation = "ignore"; // Restore config after navigation completes
    });
}
Glomerule answered 1/11, 2019 at 12:52 Comment(1)
Interesting answer if you're pretending to allow onSameUrlNavigation = "reload" for some reason IDKRevue
U
2

use ngx page scroll

 <a pageScroll href="#awesomePart">Take me to the awesomeness</a>
 <h2 id="awesomePart">This is where the awesome happens</h2>
Uppercase answered 8/1, 2019 at 17:34 Comment(3)
Nice answer, it's working well. If you are in the /home page for example, you need to do href="home#anchor". +1Intrados
You do not need a library for that, this behavior is included in the angular router.Yeoman
@Yeoman yes you are right we just need to add ` anchorScrolling: 'enabled'` in app routing module inside ExtraOptions for forRootSadie
M
-1

You need to use hash routing strategy to enable the hash scrolling.

you need to give second argument as an object like RouterModule.forRoot([],{useHash:true}}. It will work.

Mastiff answered 8/9, 2018 at 9:41 Comment(1)
hash strategy deals with hashes as routes, isn't it so?Fault

© 2022 - 2024 — McMap. All rights reserved.