Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Blazor, how to retrieve all routable Razor component names in Pages directory?

I want to programmatically generate a list of menus by iterating through the routable Razor component names as follows. How to implement GetAllRoutableRazorComponentNames() below? Is it possible?

@foreach (var filename in GetAllRoutableRazorComponentNames())
{
    <li class="nav-item px-3">
        <NavLink class="nav-link" href="@filename">
            <span class="oi oi-list-rich" aria-hidden="true">@filename</span>
        </NavLink>
    </li>
}
like image 289
xport Avatar asked Oct 28 '25 05:10

xport


1 Answers

I think the "complete" solution will also be useful for others in the future, so I made it as a community wiki. Feel free to edit as much as you want.

Thanks to the people who answered my questions here and here. I used their solutions here but with some minor adjustments.

@using System.Reflection
@using System.Text.RegularExpressions

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">Notes</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="@NavMenuCssClass" @onclick=ToggleNavMenu>
    <ul class="nav flex-column">
        @foreach (var name in GetRoutableComponentNamesForMenu())
        {
            <li class="nav-item px-3">
                <NavLink class="nav-link"
                         href=@(name=="Index"?string.Empty:name)
                         Match=@(name=="Index"?NavLinkMatch.All:NavLinkMatch.Prefix)>
                    <span class="oi oi-home" aria-hidden="true"></span>
                    @Regex.Replace(name, @"(\B[A-Z])", " $1")
                </NavLink>
            </li>
        }
    </ul>
</div>


@code {
    private bool collapseNavMenu = true;

    private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }

    public IEnumerable<string> GetRoutableComponentNamesForMenu()
    {
        var allComponents = Assembly
                .GetExecutingAssembly()
                .ExportedTypes
                .Where(t => t.IsSubclassOf(typeof(ComponentBase)));

        var routableComponents = allComponents
            .Where(c => c
                        .GetCustomAttributes(inherit: true)
                        .OfType<RouteAttribute>()
                        .Count() > 0);


        foreach (var routableComponent in routableComponents)
        {
            yield return routableComponent
                            .ToString()
                            // you need to adjust the following!
                            .Replace("Notes.Client.MenuPages.", string.Empty);
        }
    }
}

Note that

  • MenuPages is a directory in the project that only contains routable Razor components to be displayed as menu. Error page must not be there for sure!

  • The name for each components in MenuPages are in PascalCase.

As I am new to reflection, the fully qualified name prefixes are hard coded. If you know how to make it more elegant without hard-coding, feel free to edit.

like image 89
4 revs, 2 users 98%Wissen Macht Frei Avatar answered Oct 31 '25 01:10

4 revs, 2 users 98%Wissen Macht Frei



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!