Reputation: 1289
I need to know the URL of the current page in order to check if I have to apply a certain style to an element. The code below is an example.
@using Microsoft.AspNetCore.Blazor.Services
@inject IUriHelper UriHelper
@implements IDisposable
<h1>@url</h1>
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">Blazor</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li>
<NavLink href="/" Match=NavLinkMatch.All>
Home
</NavLink>
</li>
<li>
<NavLink href="/counter">
Counter
</NavLink>
</li>
<li>
<NavLink href="/fetchdata">
Fetch data
</NavLink>
</li>
</ul>
</div>
</nav>
@functions {
private string url = string.Empty;
protected override void OnInit()
{
url = UriHelper.GetAbsoluteUri();
UriHelper.OnLocationChanged += OnLocationChanged;
}
private void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
url = newUriAbsolute;
}
public void Dispose()
{
UriHelper.OnLocationChanged -= OnLocationChanged;
}
}
I used the same approach used in the NavLink component in the Blazor repository, but it did not work. Any ideas?.
Upvotes: 118
Views: 120267
Reputation: 881
Create somewhere an extension method like this:
namespace YourSolution.YourProject
{
public static class NavigationManagerExtention
{
public static string Page(this NavigationManager navigation)
{
return navigation.Uri.Substring(navigation.BaseUri.Length - 1);
}
}
}
and to get the page part of URL just call _nav.Page()
Examples:
example.com/home
it returns /home
example.com/
it returns /
If you don't need a slash char (/
) replace
return navigation.Uri.Substring(navigation.BaseUri.Length - 1);
with
return navigation.Uri.Substring(navigation.BaseUri.Length);
Upvotes: 3
Reputation: 101
In my case I only needed the Uri of the page and not the base Uri aswell.
I keep all my code in a razor.cs file so I inject NavigationManager from code-behind like this:
[Inject] public NavigationManager Navigation { get; set; }
Navigation.Uri yeilds: https://localhost:5001/nail-square-singel-shear-timber-timber
So to get the page Uri just do like this:
Navigation.Uri.Replace(Navigation.BaseUri,"")
The above yields: nail-square-singel-shear-timber-timber
Upvotes: 4
Reputation: 51645
Use the Uri
property from the NavigationManager
class.
Get it from injection before using it on .razor
pages:
@inject NavigationManager MyNavigationManager
Or like this in a .cs
file if you prefer the "code-behind" experience:
using Microsoft.AspNetCore.Components;
// ...
[Inject]
public NavigationManager MyNavigationManager {get; set;} = default!;
@page "/navigate"
@inject NavigationManager MyNavigationManager
<h1>Current URL</h1>
<p>@(MyNavigationManager.Uri)</p>
More about navigation (NavigateTo, BaseUri, ToAbsoluteUri, ToBaseRelativePath, ... ) at: URI and navigation state helpers
MyNavigationManager.Uri
#> https://localhost:5001/counter/3?q=hi
MyNavigationManager.BaseUri
#> https://localhost:5001/
MyNavigationManager.NavigateTo("http://new location")
#> Navigates to new location
MyNavigationManager.LocationChanged
#> An event that fires when the navigation location has changed.
MyNavigationManager.ToAbsoluteUri("pepe")
#> https://localhost:5001/pepe
MyNavigationManager.ToBaseRelativePath(MyNavigationManager.Uri)
#> counter/3?q=hi
Helper: AddQueryParm( "q2", "bye" ) // (*1)
#> https://localhost:5001/counter/3?q=hi&q2=bye
Helper: GetQueryParm( "q" )
#> hi
(*1)
Net6 introduces GetUriWithQueryParameter
. More info: Manipulate the query string from Blazor
Helpers code:
@code {
[Parameter]
public string Id { get; set; }
// Blazor: add parm to URL
string AddQueryParm(string parmName, string parmValue)
{
var uriBuilder = new UriBuilder(MyNavigationManager.Uri);
var q = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);
q[parmName] = parmValue;
uriBuilder.Query = q.ToString();
var newUrl = uriBuilder.ToString();
return newUrl;
}
// Blazor: get query parm from the URL
string GetQueryParm(string parmName)
{
var uriBuilder = new UriBuilder(MyNavigationManager.Uri);
var q = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);
return q[parmName] ?? "";
}
}
Upvotes: 258
Reputation: 201
First of all, inject NavigationManager
into the component in which you need to get the current URL as below:
@inject NavigationManager NavManager
Now use the below line to get the current URL:
string Url = NavManager.Uri.ToString();
Upvotes: 14
Reputation: 8932
There is no use in connecting to the OnLocationChanged
event in a page or component, as they get loaded and disposed on demand.
You should register to this event in app.cshtml as that won't be disposed.
Upvotes: 4
Reputation: 735
You should listen to a LocationChange of the IUriHelper, which triggers the function to do what you want for example:
@using Microsoft.AspNetCore.Blazor.Components
@using Microsoft.Extensions.Logging
@inject Microsoft.AspNetCore.Blazor.Services.IUriHelper UriHelper
@inject ILogger<NavItem> logger
<li class="m-menu__item @(Active ? "m-menu__item--active" : "")">
<a href=@Url class="m-menu__link ">
<span class="m-menu__item-here"></span>
<i class="m-menu__link-icon @Icon"></i>
<span class="m-menu__link-text">@Text</span>
</a>
</li>
@functions {
protected override void OnInit()
{
UriHelper.OnLocationChanged += OnLocationChanges;
}
[Parameter]
private string Url { get; set; }
[Parameter]
private string Icon { get; set; }
[Parameter]
private string Text { get; set; }
private bool Active = false;
private void OnLocationChanges(object sender, string newLocation)
{
bool active = newLocation.Contains(Url);
if(active != Active) //Only re-render the components that need it
{
Active = active;
StateHasChanged();
logger.LogInformation("Location Change To:" + newLocation);
}
}
}
Upvotes: 3