Search code examples
c#asp.netasp.net-mvcrazor-pagesasp.net-core-viewcomponent

Is there a way to nest things inside a view component (written as a tag helper) in ASP.NET?


I want to do something like this...

<vc:sidebar-submenu id=@configurationId>
    <vc:sidebar-submenu-item action-name="Index" controller-name="MapDefinitions" text="Map Definitions" />
    <vc:sidebar-submenu-item action-name="Index" controller-name="Nodes" text="Nodes" />
    <vc:sidebar-submenu-item action-name="SOIIndex" controller-name="SOIHome" text="Signals of Interest" requires-web-role-authorization=true />
    <vc:sidebar-submenu-item action-name="Home" controller-name="ProtectedFrequency" text="Protected Frequencies" />
</vc:sidebar-submenu>

The SidebarSubmenu component is quite simple.

<div class="sidebar-submenu" [email protected]>
    <ul>

    </ul>
</div>

And the SidebarSubmenuItem component is also fairly simple.

@{
    string actualCurrentPage = Context.Request.Path.ToString().Split('/')[1];
}

<a class="nav-link dropdown-level @(actualCurrentPage == Model.ExpectedCurrentPage ? "active" : null)" [email protected]>
    <div [email protected]>
        <span>@Model.Text</span>
    </div>
</a>

However, when I test this, literally anything I put 'inside' the view component doesn't appear.

Basically, my question is, is there a way to nest HTML elements and/or other view components inside another view component?

Or am I trying to use the view component in ways it was never designed for?

I guess it would become quite messy if your top-level component had several 'leaf nodes' where the nested item could possibly land... However in my case there is only one 'leaf node' (the empty element).

This is all in attempt to reduce code duplication and maintain UI code better than we currently do.

This is probably a really easy thing to do in React...

The obvious alternative to what I'm trying to do, is just "hard code" the div and ul elements, something like this:

<div class="sidebar-submenu" [email protected]>
    <ul>
        <vc:sidebar-submenu-item action-name="Index" controller-name="MapDefinitions" text="Map Definitions" />
        <vc:sidebar-submenu-item action-name="Index" controller-name="Nodes" text="Nodes" />
        <vc:sidebar-submenu-item action-name="SOIIndex" controller-name="SOIHome" text="Signals of Interest" requires-web-role-authorization=true />
        <vc:sidebar-submenu-item action-name="Home" controller-name="ProtectedFrequency" text="Protected Frequencies" />
     </ul>
</div>

Solution

  • An ASP.NET Core View Component does not support child content or nested components. It's not like a React or Blazor component. For your particular requirement, I'd suggest using anchor tag helpers. If you wanted to encapsulate the menu mark-up in its own file, include it in a partial: https://www.learnrazorpages.com/razor-pages/partial-pages

    If your menu is database driven, that's the time to use a View Component because the component's controller class supports dependency injection.