Skip to content

VladislavFurdak/BlazorNexus

Repository files navigation

BlazorNexus.Navigation

image

<button @onclick="() => _nav.Go(Routes.Aiur)">Teleport on Aiur</button>

Why?

  1. Routing using Enums is more convenient and does not rely on URI schema changing. That approach will have less error in enterprise-scale applications.
  2. Conventions are good. Let's separate "Pages" from "Components". That makes code more readable.
  3. Do not reinvent the wheel when implementing "go on the previous page", checking which is the "Current" page, parsing query string, etc.

Installing

To install the package add the following line to your csproj file replacing x.x.x with the latest version number (found at the top of this file):

<PackageReference Include="BlazorNexsus.Navigation" Version="x.x.x" />

You can also install via the .NET CLI with the following command:

dotnet add package BlazorNexsus.Navigation

If you're using Jetbrains Rider or Visual Studio you can also install via the built-in NuGet package manager.

Setup

You will need to register the navigation manager services with the service collection in your Program.cs file in Blazor WebAssembly.

public static async Task Main(string[] args)
{
    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.RootComponents.Add<App>("app");

    builder.Services.AddBlazorNexusNavigation<Routes>();

    await builder.Build().RunAsync();
}

Usage (Blazor WebAssembly)

Create an Enum that keeps your pages (same name as *.razor files):

public enum Routes
{
    CounterPage,
    HomePage,
    WeatherPage
}

for image

But, be sure, that

  1. Each Razor Page file has a navigation @page attribute
  2. The Name is the same as for Enum
  3. The *.razor files have a mandatory "Page" postfix.

And add INavigationManager in your razor views

Examples of usage

@using BlazorNexsus.Navigation
@inject INavigationManager<Routes> _navigationManager

 /** Simple use: navigate the page **/
 <button @onclick="() => _navigationManager.Go(Routes.CounterPage)">Go Counter</button>

 /** Complex usage: opens a special offer page with a bunch of parameters,
gives the ability to go back with preserving of query string params **/
 @{
        Dictionary<string,string> navigationParams =  new()
        {
            ["sectionId"] = "777",
            ["couponId"] = "49CEAE43-2004-45D1-8716-6EA0EFC407AC"
        };

        Dictionary<string,string> queryStringParams =  new()
        {
            ["utm_source"] = "email",
            ["utm_campaign"] = "weekab"
        };
    }

    <button @onclick="() => _navigationManager.Go(
                pageKey: Routes.SpecialOffer,
                newTab: false,
                backPage: Routes.Cart, 
                navigationParams,
                queryStringParams)">Check Special Offer</button>

And on the Special Offer page:

@using BlazorNexsus.Navigation
@inject INavigationManager<Routes> _navigationManager


@if (hasBackPage)
{
    <button class="btn btn-primary"
    @onclick="() => _navigationManager.Back(fallBackPageKey: Routes.Home, preserveQueryString : true)">Go Back</button>
}

@if (utm_campaign is "weekab")
{
    <div>Special offer !</div>
}

@code {
        private bool hasBackPage = false;
        private string utm_campaign = string.empty;

        protected override async Task OnInitializedAsync()
        {
            hasBackPage = await _navigationManager.HasBackPage();
            utm_campaign = _navigationManager.GetQueryStringParam<string>("utm_campaign");
        }
}

Another example of creating a menu with an active element:

@using BlazorNexsus.Navigation
@inject INavigationManager<Routes> _navigationManager

<div class="nav-item px-3">
    <a @onclick="() => _navigationManager.Go(Routes.HomePage)" class="@GetActiveClassFor(Routes.HomePage) nav-link">
        <span class="bi bi-house-door-fill" aria-hidden="true"></span> Home
    </a>
</div>
<div class="nav-item px-3">
    <a @onclick="() => _navigationManager.Go(Routes.Cart)" class="@GetActiveClassFor(Routes.Cart) nav-link">
        <span class="bi bi-cart-check-fill" aria-hidden="true"></span> Cart
    </a>
 </div>


@code{
        private string GetActiveClassFor(Routes activePage)
        {
            return _navigitaionManager.CurrentPage == activePage ? "active" : string.Empty;
        }
}

Full API specification

INavigationManager:

  • Go(pageKey);
  • Go(options);
  • Go(pageKey, newTab, backPage, navigationParams, queryParams);
  • HasBackPage();
  • Back(fallBackPageKey, preserveQueryString);
  • Refresh(browserReload);
  • CurrentPage
  • Routes
  • event LocationChanged
  • GetQueryStringParam(key)

There are 2 optional parameters on registration:

builder.Services.AddBlazorNexusNavigation<Routes>(
    pagePostfixCheck: true,
    checkUnusedKeys: true);
  • pagePostfixCheck - on "true" rises an exception if a razor Page with the @page attribute doesn't have a "Page" postfix in the filename.
  • checkUnusedKeys - on "true" raise an exception if some of the Enums don't have appropriate pages. Default values are "true"

Product roadmap (v.1.0 release)

  • Fix some minor issues, have a bug when the domain part doesn't have ":" or "." symbols
  • Add more unit tests: spaces in the query string, special symbols, different types of URIs, etc
  • Add more unit tests: a page has multiple @page attributes
  • Add more possible operations related to Query String params
  • Add the ability to use a raw query string in the Go method
  • Ability to get the underlying NavigationManager class
  • Navigation to anchor
  • Add support for BlazorServer

Enjoy 🍉🍉🍉

Thanks for donates:

  • ⭐Mykhailo Rospopchuk
  • ⭐Іnna Terletskaya