Skip to content
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

Ignore query/fragment in ShouldMatch of NavLink by default but allow overriding ShouldMatch #59903

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions src/Components/Web/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#nullable enable
virtual Microsoft.AspNetCore.Components.Routing.NavLink.ShouldMatch(string! currentUriAbsolute) -> bool
9 changes: 7 additions & 2 deletions src/Components/Web/src/Routing/NavLink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ private void OnLocationChanged(object? sender, LocationChangedEventArgs args)
}
}

private bool ShouldMatch(string currentUriAbsolute)
/// <summary>
/// Determines whether the current URI should match the link.
/// </summary>
/// <param name="currentUriAbsolute">The absolute URI of the current location.</param>
/// <returns>True if the link should be highlighted as active; otherwise, false.</returns>
protected virtual bool ShouldMatch(string currentUriAbsolute)
ilonatommy marked this conversation as resolved.
Show resolved Hide resolved
{
if (_hrefAbsolute == null)
{
Expand Down Expand Up @@ -199,7 +204,7 @@ private static bool IsStrictlyPrefixWithSeparator(string value, string prefix)

private static bool IsUnreservedCharacter(char c)
{
// Checks whether it is an unreserved character according to
// Checks whether it is an unreserved character according to
// https://datatracker.ietf.org/doc/html/rfc3986#section-2.3
// Those are characters that are allowed in a URI but do not have a reserved
// purpose (e.g. they do not separate the components of the URI)
Expand Down
28 changes: 28 additions & 0 deletions src/Components/test/E2ETest/Tests/RoutingTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,34 @@ public void CanFollowLinkDefinedInOpenShadowRoot()
AssertHighlightedLinks("Other", "Other with base-relative URL (matches all)");
}

[Fact]
public void CanOverrideNavLinkToIgnoreFragment()
{
SetUrlViaPushState("/layout-overridden/for-hash");

var app = Browser.MountTestComponent<TestRouter>();
app.FindElement(By.LinkText("Override layout with hash, no trailing slash")).Click();
Browser.Equal("This is the page with overridden layout.", () => app.FindElement(By.Id("test-info")).Text);
AssertHighlightedLinks(
"Override layout (matches all)",
"Override layout, no trailing slash (matches all)",
"Override layout with hash, no trailing slash");
}

[Fact]
public void CanOverrideNavLinkToIgnoreQuery()
{
SetUrlViaPushState("/layout-overridden");

var app = Browser.MountTestComponent<TestRouter>();
app.FindElement(By.LinkText("Override layout with query, no trailing slash")).Click();
Browser.Equal("This is the page with overridden layout.", () => app.FindElement(By.Id("test-info")).Text);
AssertHighlightedLinks(
"Override layout (matches all)",
"Override layout, no trailing slash (matches all)",
"Override layout with query, no trailing slash");
}

[Fact]
public void CanGoBackFromNotAComponent()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@page "/layout-overridden"
@page "/layout-overridden/for-hash"
@layout RouterTestLayoutNavLinksOverridden
<div id="test-info">This is the page with overridden layout.</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@using Microsoft.AspNetCore.Components.Routing
<style type="text/css">
a.active {
background-color: yellow;
font-weight: bold;
}
</style>
<ul>
<li><NavLinkIgnoreQueryAndFragmentString href="/subdir/layout-overridden/" Match=NavLinkMatch.All>Override layout (matches all)</NavLinkIgnoreQueryAndFragmentString></li>
<li><NavLinkIgnoreQueryAndFragmentString href="/subdir/layout-overridden" Match=NavLinkMatch.All>Override layout, no trailing slash (matches all)</NavLinkIgnoreQueryAndFragmentString></li>
<li><NavLinkIgnoreQueryAndFragmentString href="/subdir/layout-overridden/?abc=123">Override layout with query</NavLinkIgnoreQueryAndFragmentString></li>
<li><NavLinkIgnoreQueryAndFragmentString href="/subdir/layout-overridden?abc=123">Override layout with query, no trailing slash</NavLinkIgnoreQueryAndFragmentString></li>
<li><NavLinkIgnoreQueryAndFragmentString href="/subdir/layout-overridden/#blah">Override layout with hash</NavLinkIgnoreQueryAndFragmentString></li>
<li><NavLinkIgnoreQueryAndFragmentString href="/subdir/layout-overridden#blah">Override layout with hash, no trailing slash</NavLinkIgnoreQueryAndFragmentString></li>
<li><NavLinkIgnoreQueryAndFragmentString href="/subdir/layout-overridden/Default.html">Override layout with extension</NavLinkIgnoreQueryAndFragmentString></li>
<li><NavLinkIgnoreQueryAndFragmentString href="/subdir/layout-overridden/Other">Override Other</NavLinkIgnoreQueryAndFragmentString></li>
<li><NavLinkIgnoreQueryAndFragmentString href="/subdir/Other" Match=NavLinkMatch.All>Override Other with base-relative URL (matches all)</NavLinkIgnoreQueryAndFragmentString></li>
</ul>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@using Microsoft.AspNetCore.Components.Routing;
@inherits NavLink

@{
base.BuildRenderTree(__builder);
}

@code{

protected override bool ShouldMatch(string currentUriAbsolute)
{
if (base.ShouldMatch(currentUriAbsolute))
{
return true;
}

var originalMatch = base.Match;
base.Match = NavLinkMatch.All;
string uriWithoutQueryAndFragment = GetUriIgnoreQueryAndFragment(currentUriAbsolute);
var shouldMatch = base.ShouldMatch(uriWithoutQueryAndFragment);
base.Match = originalMatch;
return shouldMatch;
}

private string GetUriIgnoreQueryAndFragment(string uri) =>
new Uri(uri).GetLeftPart(UriPartial.Path);
}
ilonatommy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@using Microsoft.AspNetCore.Components
@inherits LayoutComponentBase

@Body

<BasicTestApp.RouterTest.LinksOverridden />
Loading