Search code examples
c#blazorblazor-webassembly

Blazor - How to get layout @Body path?


I am solving problem with breadcrumb navigation and dynamic showing (I want to avoid have in every razor component (one of Pages) static data. Thank you in forward.

Problem: how to get path of the @Body component? In the body is of course the one of (default folder name in project) Pages. So line 1 of "body itself" is @page "/somePage"...

My (shortened) layout:

<div class="page">
    <div class="main">
        <div class="top-row TitleButtonList @((closedLeftBar) ? "TitleButtonListClose" : "") ">
            <TitleButton />
        </div>
        <div class="top-row">
            <BreadcrumbNav breadCrumbData="breadCrumbDatas"></BreadcrumbNav>
            <p>Error test name: @path</p>
        </div>

        <div class="content px-4 @((closedLeftBar) ? "contentClose col-md-10" : "contentOpen col-md-9")">
            @Body
            <FOLButtons />
        </div>
    </div>
</div>

@code {
    public List<BreadCrumbData> breadCrumbDatas;
    string path = string.Empty;

    protected override void OnInitialized()
    {
        breadCrumbDatas = breadCrumbService.GetProperList();
        path = ??????
    }
}

Model of BreadCrumb:

public class BreadCrumbData
    {
        [Required]
        public string Text { get; set; }
        [Required]
        public string URL { get; set; }
        [Required]
        public int Level { get; set; }

        [Required]
            #nullable enable
        public string? ParentURL { get; set; }

        public BreadCrumbData(string text, string url, int level, string parentURL)
        {
            Text = text;
            URL = url;
            Level = level;
            ParentURL = parentURL;
        }
    }

Breadcrumb component (that one what is in layout)

<nav aria-label="breadcrumb">
    <ol class="breadcrumb">
        @if (breadCrumbData != null)
        {

            @foreach (var item in breadCrumbData)
            {
                @if (item == breadCrumbData.Last())
                {
                    <li class="breadcrumb-item active" aria-current="page">@item.Text</li>

                }
                else
                {
                    <li class="breadcrumb-item"><a href="@item.URL">@item.Text</a></li>
                }
            }
        }
    </ol>
</nav>

@code {
    [Parameter]
    public List<BreadCrumbData> breadCrumbData { get; set; }
}

Solution

  • Blazor provides the NavigationManager for this purpose (see Blazor routing):

    @inject NavigationManager NavigationManager;
    
    protected override void OnInitialized()
    {
        breadCrumbDatas = breadCrumbService.GetProperList();
    
        // Get everything after the domain + '/' (e.g. after "https://example.com/")
        path = NavigationManager.Uri.Substring(Navigator.BaseUri.Length); 
    
        // You can also listen for a path change by subscribing to 
        //     NavigationManager.LocationChanged.
    }
    

    A couple notes/suggestions:

    • Since NavigationManager can be injected, you don't need to pass it down to your BreadCrumbs component as a parameter (unless you are using the component for something other than URL paths). You can directly inject it into your BreadCrumbs component:
    @inject NavigationManager NavigationManager;
    
    <nav aria-label="breadcrumb">
        <ol class="breadcrumb">
    
    • @Body isn't a component: it is a RenderFragment.
    • @Body doesn't have a path, per se; pages (designated with @page) do. Routing is managed by App.razor and configured in Startup.cs.