0

I have a Component with page attribute that matches parameters for selected parent and child category in a delivery platform.

@page "/{Alias}/speisekarte"
@page "/{Alias}/speisekarte/{CategoryText}"
@page "/{Alias}/speisekarte/{CategoryText}/{SubCategoryText}"

Here we have a sample the parent category "Pizza" and the child category "MyPizza":

https://v7pizzaboy.gastroblitz.de/duesseldorf-derendorf/speisekarte/pizza/mypizza

Problem is now that when changing the category via click it always jumps to the very beginning when switching to new Url of the SAME Component "MenuPage.razor".

    <div class="swiper-slide swiper-slide-active" style="width: 136.25px;"
        @onclick="(() => GotoCategory(category.Permlink))">
        <a class="@(category == CurrentParentCategory ? "active" : "")" href="#" @onclick:preventDefault>
             <img src="/img/@category.NavigationIcon" height="36" alt="Aktion" class="">
             <span>@category.Name</span>
        </a>
    </div>

No matter if I use a href with destination link or NavigationManager:

    public void GotoCategory(string permLink)
    {
        var url = $"/{My.Store.PrimaryAlias}/speisekarte/{permLink}";
        NavigationManager.NavigateTo(url);
    }

you can try yourself on page (link above):

  1. scroll down
  2. then click navigation link

Question is how can I change the given data plus the url but stay at the same scroll position for good user experience?

baer999
  • 810
  • 2
  • 14
  • 26

4 Answers4

1

In theory, you could store the scrolling position, somehow (you need JavaScript interop for this). However, if also data changes, it makes no sense to use a previous scrolling.

On the other side, if the same position makes sense also with changed data, probably the best solution is to avoid leaving the page. You can achieve this by using a callback to change the data that bind your page. That is you use click events to load different data on the same page, thus changing only the parts of the page that need to be changed.

For sure this would give a better experience to the user and better performance since you will not refresh the whole page but just some parts, and you would avoid the navigation. As a side effect, also other state-information on the page will not be lost.

Francesco Abbruzzese
  • 4,139
  • 1
  • 17
  • 18
0

More than likely, the NavigateTo function is causing the page to reinitialize? Anyway, I would solve this by adding a static variable to hold the scroll position of the browser. Set that before navigating. Then, in OnAfterRender override, I would call a Javascript interop (IJSRuntime) to scroll the container back to the previous spot.

  • yes that is a good idea, problem is that I'm developing Server Side Blazor where you always get a flickering until the correct Scroll Position is set. Maybe it is possible to just load the Articles and set the URL new - so to "fake" a new page call after click (set new SelectedCategory, load that articles and override the URL path). Is this possible? – baer999 Nov 20 '20 at 16:13
  • So, when using Server Side Blazor, you cannot call a JavaScript function on the client? No way to tell the client to run a script? – Jim Bendler Dec 18 '20 at 19:05
0

You can solve this in a couple of ways;

or if you would rather avoid JavaScript you might be able to include anchor tags in your links.

Mark Cooper
  • 6,738
  • 5
  • 54
  • 92
0

My solution was to use pushState

window.history.pushState({page: "another"}, "another page", "example.html");

so, I created a helper class

using Microsoft.JSInterop;
using System.Threading.Tasks;

public static class Helpers
{
    public async static Task ChangeRouteWithoutReload(IJSRuntime js, string newRoute, string pageName)
    {
        await js.InvokeAsync<string>("window.history.pushState", new { page = pageName }, pageName, newRoute);
    }
}

which can be used like this

[Inject]
protected IJSRuntime JS { get; set; } = null;

private async Task ChangeRoute()
{
    await JsInteropHelpers.ChangeRouteWithoutReload(JS, "/new-route", "New Page Name");
}
Sebastian
  • 1,109
  • 4
  • 17
  • 33