New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Router: Provide support for handling the URL hash #6595

Closed
brandonroberts opened this Issue Jan 20, 2016 · 70 comments

Comments

@brandonroberts
Contributor

brandonroberts commented Jan 20, 2016

If I have a URL with a hash, when I navigate to it, the hash is dropped from the URL and the page does not jump to the anchor tag. If I have to go an existing route and click a link with the hash at the end, it jumps to the anchor tag correctly. Also, their isn't a public api to get/set the hash outside of using window.location.hash

@ThiagoT1

This comment has been minimized.

Show comment
Hide comment
@ThiagoT1

ThiagoT1 commented Feb 21, 2016

+1

@tamalnath

This comment has been minimized.

Show comment
Hide comment
@tamalnath

tamalnath Mar 1, 2016

Do we have any update on this?

tamalnath commented Mar 1, 2016

Do we have any update on this?

@yeegr

This comment has been minimized.

Show comment
Hide comment
@yeegr

yeegr Mar 19, 2016

Yes, I need this really quick as well.

yeegr commented Mar 19, 2016

Yes, I need this really quick as well.

@p-mcgowan

This comment has been minimized.

Show comment
Hide comment
@p-mcgowan

p-mcgowan Apr 6, 2016

+1 please fix. This is mandatory for md-tab routing as well.

p-mcgowan commented Apr 6, 2016

+1 please fix. This is mandatory for md-tab routing as well.

@afirdousi

This comment has been minimized.

Show comment
Hide comment
@afirdousi

afirdousi Apr 8, 2016

Are there any plans on this ?

I was thinking on a few scenarios in my angular 2 prod app. As for designing a solution, will it makes sense to have these values on each route in @RouteConfig as well as when the user uses router.navigate(). The user should be allowed to navigate to a position or #hash, by default to the top (0,0)

It may look something like:

@RouteConfig([ { path: '/route1', component:Component1, name:'R1' }, // Scrolls to default (0,0) { path: '/route2', component:Component2, name:'R2', position:(0,600) }, // open at 600px vertically { path: '/route2', component:Component2, name:'R3', hash:"#about" } // opens at #about

and on router.navigate it may look like

this.router.navigate([ "R2" , { } , { position:(0,600) } ]) //or this.router.navigate([ "R3" , { } , { hash:"#about" } ])

I believe we need changes in Instruction and ComponentInstruction classes down i angular/route.

This or any other better solutions we implement, will it jump to the position or scroll smooth to the specified position. Idk.

afirdousi commented Apr 8, 2016

Are there any plans on this ?

I was thinking on a few scenarios in my angular 2 prod app. As for designing a solution, will it makes sense to have these values on each route in @RouteConfig as well as when the user uses router.navigate(). The user should be allowed to navigate to a position or #hash, by default to the top (0,0)

It may look something like:

@RouteConfig([ { path: '/route1', component:Component1, name:'R1' }, // Scrolls to default (0,0) { path: '/route2', component:Component2, name:'R2', position:(0,600) }, // open at 600px vertically { path: '/route2', component:Component2, name:'R3', hash:"#about" } // opens at #about

and on router.navigate it may look like

this.router.navigate([ "R2" , { } , { position:(0,600) } ]) //or this.router.navigate([ "R3" , { } , { hash:"#about" } ])

I believe we need changes in Instruction and ComponentInstruction classes down i angular/route.

This or any other better solutions we implement, will it jump to the position or scroll smooth to the specified position. Idk.

@kucharzyk

This comment has been minimized.

Show comment
Hide comment
@kucharzyk

kucharzyk Apr 21, 2016

+1
please fix this issue

kucharzyk commented Apr 21, 2016

+1
please fix this issue

@emesx

This comment has been minimized.

Show comment
Hide comment
@emesx

emesx commented Apr 21, 2016

+1 (#8105)

@brandonroberts

This comment has been minimized.

Show comment
Hide comment
@brandonroberts

brandonroberts Jun 24, 2016

Contributor

Support for fragments has been added to the v3 router

Contributor

brandonroberts commented Jun 24, 2016

Support for fragments has been added to the v3 router

@mark-langer

This comment has been minimized.

Show comment
Hide comment
@mark-langer

mark-langer Jul 2, 2016

The router at release alpha.8 does update the URL - including the hash - correctly but does not make the view jump to the anchor specified by that hash.

Let's assume you are at this location:
www.example.org/Comp1/Comp2

Then clicking this link:
<a [routerLink]="['Comp3']" fragment="Test">Jump to 'Test' anchor </a>

will update the browser's url to:
www.example.org/Comp1/Comp2/Comp3#Test

So far, so good.

However, the view does not automatically scroll/jump to the element with id "Test". Are there any plans to fix this or am I just missing something?

mark-langer commented Jul 2, 2016

The router at release alpha.8 does update the URL - including the hash - correctly but does not make the view jump to the anchor specified by that hash.

Let's assume you are at this location:
www.example.org/Comp1/Comp2

Then clicking this link:
<a [routerLink]="['Comp3']" fragment="Test">Jump to 'Test' anchor </a>

will update the browser's url to:
www.example.org/Comp1/Comp2/Comp3#Test

So far, so good.

However, the view does not automatically scroll/jump to the element with id "Test". Are there any plans to fix this or am I just missing something?

@justme1

This comment has been minimized.

Show comment
Hide comment
@justme1

justme1 Jul 9, 2016

Using this._router.navigate( ['/feed', id ], {fragment: 'comments'});

How can I retrieve the fragment in ngOnInit so I can focus on the comments section?

justme1 commented Jul 9, 2016

Using this._router.navigate( ['/feed', id ], {fragment: 'comments'});

How can I retrieve the fragment in ngOnInit so I can focus on the comments section?

@justme1

This comment has been minimized.

Show comment
Hide comment
@justme1

justme1 Jul 9, 2016

Found the answer:

http://victorsavkin.com/post/145672529346/angular-router

 constructor(private router:Router){
        const f: Observable<string> = _router.routerState.fragment;
        f.subscribe(params => {
             debugger; // params == 'comments'
        });

justme1 commented Jul 9, 2016

Found the answer:

http://victorsavkin.com/post/145672529346/angular-router

 constructor(private router:Router){
        const f: Observable<string> = _router.routerState.fragment;
        f.subscribe(params => {
             debugger; // params == 'comments'
        });
@goelinsights

This comment has been minimized.

Show comment
Hide comment
@goelinsights

goelinsights Aug 22, 2016

@mark-langer did you ever get this working? Stuck in the same place where the #fragment works in the link but browser doesn't scroll to the id location.

goelinsights commented Aug 22, 2016

@mark-langer did you ever get this working? Stuck in the same place where the #fragment works in the link but browser doesn't scroll to the id location.

@mark-langer

This comment has been minimized.

Show comment
Hide comment
@mark-langer

mark-langer Aug 22, 2016

Nope, I just stumbled upon this issue on stackoverflow. I didn't need to fix this for my own application. I haven't tried it since alpha.8, though. Have you tried if this works with RC.5?

mark-langer commented Aug 22, 2016

Nope, I just stumbled upon this issue on stackoverflow. I didn't need to fix this for my own application. I haven't tried it since alpha.8, though. Have you tried if this works with RC.5?

@goelinsights

This comment has been minimized.

Show comment
Hide comment
@goelinsights

goelinsights Aug 22, 2016

It’s creating the #fragment in the route but not navigating to it via the angular router (v3) and I’m in RC4 currently. On page refresh it works, but that kind of defeats the point.

From: Mark Langer notifications@github.com
Reply-To: angular/angular reply@reply.github.com
Date: Monday, August 22, 2016 at 12:48 PM
To: angular/angular angular@noreply.github.com
Cc: Vijay Goel vijay@goelinsights.com, Comment comment@noreply.github.com
Subject: Re: [angular/angular] Router: Provide support for handling the URL hash (#6595)

Nope, I just stumbled upon this issue on stackoverflow. I didn't need to fix this for my own application. I haven't tried it since alpha.8, though. Have you tried if this works with RC.5?


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

{"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/angular/angular","title":"angular/angular","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/angular/angular"}},"updates":{"snippets":[{"icon":"PERSON","message":"@mark-langer in #6595: Nope, I just stumbled upon this issue on stackoverflow. I didn't need to fix this for my own application. I haven't tried it since alpha.8, though. Have you tried if this works with RC.5?"}],"action":{"name":"View Issue","url":"https://github.com/angular/angular/issues/6595#issuecomment-241527913"}}}

goelinsights commented Aug 22, 2016

It’s creating the #fragment in the route but not navigating to it via the angular router (v3) and I’m in RC4 currently. On page refresh it works, but that kind of defeats the point.

From: Mark Langer notifications@github.com
Reply-To: angular/angular reply@reply.github.com
Date: Monday, August 22, 2016 at 12:48 PM
To: angular/angular angular@noreply.github.com
Cc: Vijay Goel vijay@goelinsights.com, Comment comment@noreply.github.com
Subject: Re: [angular/angular] Router: Provide support for handling the URL hash (#6595)

Nope, I just stumbled upon this issue on stackoverflow. I didn't need to fix this for my own application. I haven't tried it since alpha.8, though. Have you tried if this works with RC.5?


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

{"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/angular/angular","title":"angular/angular","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/angular/angular"}},"updates":{"snippets":[{"icon":"PERSON","message":"@mark-langer in #6595: Nope, I just stumbled upon this issue on stackoverflow. I didn't need to fix this for my own application. I haven't tried it since alpha.8, though. Have you tried if this works with RC.5?"}],"action":{"name":"View Issue","url":"https://github.com/angular/angular/issues/6595#issuecomment-241527913"}}}

@mark-langer

This comment has been minimized.

Show comment
Hide comment
@mark-langer

mark-langer Aug 22, 2016

Yes, absolutely agreed. Maybe the Chuck Norris of routing, @brandonroberts, can help?

mark-langer commented Aug 22, 2016

Yes, absolutely agreed. Maybe the Chuck Norris of routing, @brandonroberts, can help?

@xmcax

This comment has been minimized.

Show comment
Hide comment
@xmcax

xmcax Dec 19, 2017

Workaround provided by @badcoder28, would be fine, if it wasn't for the fact that it works only the first time you use it. If you click the link second time, URL does not get updated and so Observable does not emit anything...

xmcax commented Dec 19, 2017

Workaround provided by @badcoder28, would be fine, if it wasn't for the fact that it works only the first time you use it. If you click the link second time, URL does not get updated and so Observable does not emit anything...

@waverly

This comment has been minimized.

Show comment
Hide comment
@waverly

waverly Jan 8, 2018

I'm attempting to get routing working with a fragment but I'm having timing issues. I've tried everything on this thread to no avail. Any ideas?? Please see my Stack Overflow below

https://stackoverflow.com/questions/48141804/angular-2-routing-with-fragments-async-data -

waverly commented Jan 8, 2018

I'm attempting to get routing working with a fragment but I'm having timing issues. I've tried everything on this thread to no avail. Any ideas?? Please see my Stack Overflow below

https://stackoverflow.com/questions/48141804/angular-2-routing-with-fragments-async-data -

@bennadel

This comment has been minimized.

Show comment
Hide comment
@bennadel

bennadel Jan 12, 2018

I just ran into this same issue (jump-to-anchor functionality). So, I wanted to throw my hat into the ring -- I took an approach that polyfills the behavior with a Module. This way, your code doesn't actually have to change; and the polyfill can be removed once Angular core implements the fragment navigation.

It works by creating a directive that binds to selector: "[id], a[name]" and then monitors the activatedRoute.fragment stream. So, not all that different from some of the previous suggestions. But, different in that your app doesn't really have to "know" about any of this.

bennadel commented Jan 12, 2018

I just ran into this same issue (jump-to-anchor functionality). So, I wanted to throw my hat into the ring -- I took an approach that polyfills the behavior with a Module. This way, your code doesn't actually have to change; and the polyfill can be removed once Angular core implements the fragment navigation.

It works by creating a directive that binds to selector: "[id], a[name]" and then monitors the activatedRoute.fragment stream. So, not all that different from some of the previous suggestions. But, different in that your app doesn't really have to "know" about any of this.

@jorgjanke

This comment has been minimized.

Show comment
Hide comment
@jorgjanke

jorgjanke Jan 24, 2018

This worked for me best for all navigation changes:

constructor(private route: ActivatedRoute) {}

ngOnInit() {
   this._sub = this.route.fragment.subscribe((hash: string) => {
      if (hash) {
        const cmp = document.getElementById(hash);
        if (cmp) {
          cmp.scrollIntoView();
        }
      } else {
        window.scrollTo(0, 0);
      }
    });
  } 

jorgjanke commented Jan 24, 2018

This worked for me best for all navigation changes:

constructor(private route: ActivatedRoute) {}

ngOnInit() {
   this._sub = this.route.fragment.subscribe((hash: string) => {
      if (hash) {
        const cmp = document.getElementById(hash);
        if (cmp) {
          cmp.scrollIntoView();
        }
      } else {
        window.scrollTo(0, 0);
      }
    });
  } 
@paulogr

This comment has been minimized.

Show comment
Hide comment
@paulogr

paulogr Feb 4, 2018

I simple do this

@ViewChild('myanchor') myanchor
...
...
gotoMyAnchor() {
  this.myanchor.nativeElement.scrollIntoView()
}

Works all the time :)
Hope it helps.

paulogr commented Feb 4, 2018

I simple do this

@ViewChild('myanchor') myanchor
...
...
gotoMyAnchor() {
  this.myanchor.nativeElement.scrollIntoView()
}

Works all the time :)
Hope it helps.

@ehegnes

This comment has been minimized.

Show comment
Hide comment
@ehegnes

ehegnes Feb 4, 2018

As I understand it, @paulogr's method is a more traditional way to do something like this in Angular, since we're not supposed to be touching the DOM ourselves. Right?

ehegnes commented Feb 4, 2018

As I understand it, @paulogr's method is a more traditional way to do something like this in Angular, since we're not supposed to be touching the DOM ourselves. Right?

@ecerta

This comment has been minimized.

Show comment
Hide comment
@ecerta

ecerta Feb 5, 2018

@poulogr 's approach doesn't account for tabindex adjustment for keyboard-only users, though. Someone using a keyboard will hit enter on that link, the page will scroll, and then when they go to tab again, the page'll jump right back up to where it was.

ecerta commented Feb 5, 2018

@poulogr 's approach doesn't account for tabindex adjustment for keyboard-only users, though. Someone using a keyboard will hit enter on that link, the page will scroll, and then when they go to tab again, the page'll jump right back up to where it was.

@mgb389

This comment has been minimized.

Show comment
Hide comment
@mgb389

mgb389 Feb 9, 2018

This is by far the most straightforward solution I've seen so far... don't remember who came up with it but I guess this is how you are supposed to do it. The fragment attribute just changes the URL but don't jump into the section, so you need to add the anchor tag within the tag you are using to complete the trick.

  <div [routerLink]="['pagex']" fragment="sectiony">
           <a href="#sectiony">Jump to 'Section Y' anchor in page X  </a>
  </div>

mgb389 commented Feb 9, 2018

This is by far the most straightforward solution I've seen so far... don't remember who came up with it but I guess this is how you are supposed to do it. The fragment attribute just changes the URL but don't jump into the section, so you need to add the anchor tag within the tag you are using to complete the trick.

  <div [routerLink]="['pagex']" fragment="sectiony">
           <a href="#sectiony">Jump to 'Section Y' anchor in page X  </a>
  </div>
@bluefire2121

This comment has been minimized.

Show comment
Hide comment
@bluefire2121

bluefire2121 Feb 20, 2018

When will the anchor service be added to Angular? I need this to build accessible apps and not having this feature isolates an enormous community. Please prioritize getting this developed. Thank you.

bluefire2121 commented Feb 20, 2018

When will the anchor service be added to Angular? I need this to build accessible apps and not having this feature isolates an enormous community. Please prioritize getting this developed. Thank you.

@omaracrystal

This comment has been minimized.

Show comment
Hide comment
@omaracrystal

omaracrystal Feb 22, 2018

@jorgjanke Your solution will navigate to the correct id on the page but then disregards the styling for routerLinkActive.

I'm also having a hard time applying the "fragment" attribute value to navigate to the element with that id... while routerLinkActive stays intact...

The following applies the correct active styling on click - but doesn't go to the correct route on the page (#hash)

   <li class="nav-item">
      <a [routerLink]='link'
         routerLinkActive="router-link-active"
         fragment="services"
         (click)="goToRoute('services')">Services</a>
    </li>

it does work with the following function - however - I'm wondering if this is really the best solution

  goToRoute(id) {
    document.getElementById(id).scrollIntoView();
  }

omaracrystal commented Feb 22, 2018

@jorgjanke Your solution will navigate to the correct id on the page but then disregards the styling for routerLinkActive.

I'm also having a hard time applying the "fragment" attribute value to navigate to the element with that id... while routerLinkActive stays intact...

The following applies the correct active styling on click - but doesn't go to the correct route on the page (#hash)

   <li class="nav-item">
      <a [routerLink]='link'
         routerLinkActive="router-link-active"
         fragment="services"
         (click)="goToRoute('services')">Services</a>
    </li>

it does work with the following function - however - I'm wondering if this is really the best solution

  goToRoute(id) {
    document.getElementById(id).scrollIntoView();
  }
@briancodes

This comment has been minimized.

Show comment
Hide comment
@briancodes

briancodes Mar 1, 2018

@omaracrystal That is similar to how I got around the issue also. Except instead of using (click) I have subscribed to fragment change - this also covers the case where the user manually refreshes:
this.route.fragment.subscribe(this.handleFragmentChange); - where route is the ActivatedRoute

Update: Clicking on the link twice does not work with this solution - the fragment does not change, so the event does not fire. Have reverted to using (click) event

briancodes commented Mar 1, 2018

@omaracrystal That is similar to how I got around the issue also. Except instead of using (click) I have subscribed to fragment change - this also covers the case where the user manually refreshes:
this.route.fragment.subscribe(this.handleFragmentChange); - where route is the ActivatedRoute

Update: Clicking on the link twice does not work with this solution - the fragment does not change, so the event does not fire. Have reverted to using (click) event

@jerrystarry

This comment has been minimized.

Show comment
Hide comment
@jerrystarry

jerrystarry Mar 17, 2018

Was this bug have fixed?

jerrystarry commented Mar 17, 2018

Was this bug have fixed?

@SteamWind

This comment has been minimized.

Show comment
Hide comment
@SteamWind

SteamWind Mar 22, 2018

@jiangjianyu as you can see, the issue is Open... And not assigned.
That's weird that nobody in one year tried to do something.

SteamWind commented Mar 22, 2018

@jiangjianyu as you can see, the issue is Open... And not assigned.
That's weird that nobody in one year tried to do something.

@ozknemoy

This comment has been minimized.

Show comment
Hide comment
@ozknemoy

ozknemoy Apr 28, 2018

may be this code may help someone

@Directive({
  selector : '[href]',
  host : {
    '(click)' : 'click($event)'
  },
})
export class HrefDirective {
  @Input() private href;
  private target = this.el.nativeElement.getAttribute('target');

  constructor(private el: ElementRef) {}

  click(event) {
    window.open(this.href, this.target)
  }
}

<a href="#section-1" target="_self" class="header_nav--link">Some link</a>

ozknemoy commented Apr 28, 2018

may be this code may help someone

@Directive({
  selector : '[href]',
  host : {
    '(click)' : 'click($event)'
  },
})
export class HrefDirective {
  @Input() private href;
  private target = this.el.nativeElement.getAttribute('target');

  constructor(private el: ElementRef) {}

  click(event) {
    window.open(this.href, this.target)
  }
}

<a href="#section-1" target="_self" class="header_nav--link">Some link</a>

@ctrimm ctrimm referenced this issue Jun 6, 2018

Open

FAQ Updates #488

0 of 3 tasks complete

jasonaden added a commit to vsavkin/angular that referenced this issue Jun 7, 2018

feat(router): implement scrolling restoration service
For documentation, see `RouterModule.scrollPositionRestoration`

Fixes #13636 #10929 #7791 #6595

mhevery added a commit that referenced this issue Jun 8, 2018

feat(router): implement scrolling restoration service (#20030)
For documentation, see `RouterModule.scrollPositionRestoration`

Fixes #13636 #10929 #7791 #6595

PR Close #20030
@brandonroberts

This comment has been minimized.

Show comment
Hide comment
@brandonroberts

brandonroberts Jun 8, 2018

Contributor

Fixed via #20030

Contributor

brandonroberts commented Jun 8, 2018

Fixed via #20030

@rtm

This comment has been minimized.

Show comment
Hide comment
@rtm

rtm Sep 22, 2018

@brandonroberts I'm confused. You say this is "fixed", pointing to a patch which restores scroll position when returning to a page, but isn't this issue (see the title) originally about correct handling of hashes (fragments), or am I missing something?

rtm commented Sep 22, 2018

@brandonroberts I'm confused. You say this is "fixed", pointing to a patch which restores scroll position when returning to a page, but isn't this issue (see the title) originally about correct handling of hashes (fragments), or am I missing something?

@brandonroberts

This comment has been minimized.

Show comment
Hide comment
@brandonroberts

brandonroberts Sep 24, 2018

Contributor

@rtm the PR adds support for handling fragments in addition to restoring thr scroll position when navigating between pages.

Contributor

brandonroberts commented Sep 24, 2018

@rtm the PR adds support for handling fragments in addition to restoring thr scroll position when navigating between pages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment