Skip to content

fix(router): support anchor fragments in href - #31172

Merged
ShaneK merged 4 commits into
mainfrom
FW-6958
May 28, 2026
Merged

ShaneK merged 4 commits into
mainfrom
FW-6958

Conversation

@ShaneK

@ShaneK ShaneK commented May 27, 2026 •

Copy link
Copy Markdown
Member

Issue number: resolves #19566, resolves #19365


What is the current behavior?

Clicking an ion-router-link whose href contains a #fragment (e.g. /catalog#pens) fails to navigate and logs not part of the routing set. parsePath in core/src/components/router/utils/path.ts only splits on ?, so the fragment gets folded into the last path segment and no registered route matches. Even when navigation succeeds, the matching anchor is never scrolled into view.

What is the new behavior?

parsePath extracts the fragment as a separate field, and writeSegments writes it back onto the URL via pushState. Routes match against the path segments alone, so /catalog#pens resolves to the /catalog route as expected.

After writeNavStateRoot resolves, the router polls a few animation frames for an element matching the fragment inside the active page, then smooth-scrolls to it via ion-content.scrollToPoint, falling back to Element.scrollIntoView when the target sits outside ion-content. A fragmentScrollToken cancels any in-flight scroll the moment a newer setSegments runs.

Does this introduce a breaking change?

  • Yes
  • No

Other information

The fragment lookup scopes to the last .ion-page:not(.ion-page-hidden) in the document. Nested outlets can have multiple non-hidden pages mounted at once, and an identically-named anchor on a parent page would otherwise win over the leaf the user is viewing.

Preview pages:

@ShaneK
ShaneK requested a review from a team as a code owner May 27, 2026 19:58
@ShaneK
ShaneK requested a review from BenOsodrac May 27, 2026 19:58
@vercel

vercel Bot commented May 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ionic-framework Ready Ready Preview, Comment May 28, 2026 7:28pm

Request Review

@thetaPC thetaPC left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, left a question

Comment thread core/src/components/router/test/basic/router.e2e.ts

@brandyscarney brandyscarney left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks really good and passed my testing. Just a few optional comments on the tests but overall a lot of great coverage was added!

Comment thread core/src/components/router/test/basic/router.e2e.ts
Comment thread core/src/components/router/test/basic/router.e2e.ts
Comment thread core/src/components/router/test/dom.spec.tsx
@ShaneK
ShaneK added this pull request to the merge queue May 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 28, 2026
@ShaneK
ShaneK added this pull request to the merge queue May 28, 2026
Merged via the queue into main with commit a982516 May 28, 2026
51 checks passed
@ShaneK
ShaneK deleted the FW-6958 branch May 28, 2026 20:18
HappyKnuckles pushed a commit to HappyKnuckles/ionic-framework that referenced this pull request Oct 3, 2026
Issue number: resolves ionic-team#19566, resolves ionic-team#19365

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?

Clicking an `ion-router-link` whose `href` contains a `#fragment` (e.g.
`/catalog#pens`) fails to navigate and logs `not part of the routing
set`. `parsePath` in `core/src/components/router/utils/path.ts` only
splits on `?`, so the fragment gets folded into the last path segment
and no registered route matches. Even when navigation succeeds, the
matching anchor is never scrolled into view.

## What is the new behavior?

`parsePath` extracts the fragment as a separate field, and
`writeSegments` writes it back onto the URL via `pushState`. Routes
match against the path segments alone, so `/catalog#pens` resolves to
the `/catalog` route as expected.

After `writeNavStateRoot` resolves, the router polls a few animation
frames for an element matching the fragment inside the active page, then
smooth-scrolls to it via `ion-content.scrollToPoint`, falling back to
`Element.scrollIntoView` when the target sits outside `ion-content`. A
`fragmentScrollToken` cancels any in-flight scroll the moment a newer
`setSegments` runs.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

The fragment lookup scopes to the last `.ion-page:not(.ion-page-hidden)`
in the document. Nested outlets can have multiple non-hidden pages
mounted at once, and an identically-named anchor on a parent page would
otherwise win over the leaf the user is viewing.

Preview pages:
-
[router/basic](https://ionic-framework-git-fw-6958-ionic1.vercel.app/src/components/router/test/basic#/two)

This branch was successfully deployed

1 active deployment
Preview — 637eab14 Deployed May 28, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: core @ionic/core package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: ion-router-link can't link to another page's anchor bug: routing integrations don't support hash links

3 participants