How can I make a simple "jump to" part of already loaded page in Blazor? Like this in HTML:
<a href="#contact">Contact us</a>
...
<section id="contact">
Ideally I also want to have it smooth scroll down to this section. Thought I would try to solve this with CSS, but maybe not possible?
In Blazor, you can call a JavaScript method using JavaScript interop to scroll the page to the top position. In the following code, the button event triggers when the button is clicked and scrolls to the page top.
The scrollTo method: The scrollTo() is used to scroll to the specified element in the browser.
The anchor tag helper targets the HTML anchor ( <a> ) tag which is used to generate relative links from the values passed to various custom attributes.
By using the <Style> tag, we will add the scroll options in HTML Page itself.
I've solved this by using a button
and then writing some inline Javascript in the markup. You can generalize this to a Blazor component for bonus points!
<button type="button" onclick="document.getElementById('contact').scrollIntoView({behavior:'smooth'})">Contact us</button>
...
<section id="contact">
What you need is the hashed routes features of Blazor. But, alas, no such features do exist yet. I'd suggest you use JSIterop to perform this task: Create a JavaScript that performs the navigation, and pass it an ElementRef object.
Hope this helps...
Edit: The following is an adaptation of the best workaround solution I've found in Github...
Ordinarily, when you click the link to contact, you get redirected to the route http://localhost:5000/mypage#contact, but will be at the top of the page. The fragment of the route is not used for selection of a specific HTML element.
The current workaround is to write explicit code that interprets the URL. In the example above, we could use a little bit of JavaScript and then call that from our Blazor code:
mypage.cshtml:
@page "/mypage"
@inject Microsoft.AspNetCore.Components.Services.IUriHelper UriHelper
<nav>
<a href="#contact">contact</a>
</nav>
<section>
<h2 id="contact">contact</h2>
</section>
@functions {
protected override void OnInit()
{
NavigateToElement();
UriHelper.OnLocationChanged += OnLocationChanges;
}
private void OnLocationChanges(object sender, string location) => NavigateToElement();
private void NavigateToElement()
{
var url = UriHelper.GetAbsoluteUri();
var fragment = new Uri(url).Fragment;
if(string.IsNullOrEmpty(fragment))
{
return;
}
var elementId = fragment.StartsWith("#") ? fragment.Substring(1) : fragment;
if(string.IsNullOrEmpty(elementId))
{
return;
}
ScrollToElementId(elementId);
}
private static bool ScrollToElementId(string elementId)
{
return JSRuntime.Current.InvokeAsync<bool>("scrollToElementId", elementId).GetAwaiter().GetResult();
}
}
index.html:
<script>
window.scrollToElementId = (elementId) => {
console.info('scrolling to element', elementId);
var element = document.getElementById(elementId);
if(!element)
{
console.warn('element was not found', elementId);
return false;
}
element.scrollIntoView();
return true;
}
</script>
Note: If you're using Blazor version .9.0, you should inject the IJSRuntime Please, let me know if this solution works for you...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With