I am starting to dive in deeper to ASP.NET Core and probably my #1 feature with Blazor is the ability to reuse components with RenderFragment
parameters, such as:
<div class="dropdown is-right" id="@this.ClientId">
<!--trigger button-->
<div class="dropdown-trigger">
<button class="button" aria-label="@this.AriaLabel" aria-haspopup="true" aria-expanded="false" aria-controls="@($"{this.ClientId}_dropdown")">
<i class="fas @this.Icon"></i>
</button>
</div>
<!--dropdown-->
<div class="dropdown-menu is-text-align-right" id="@($"{this.ClientId}_dropdown")" aria-hidden="true" role="menu">
<div class="dropdown-content">
@ChildContent
</div>
</div>
</div>
The C# for this component is basic as well (main property is a RenderFragment
called ChildContent
that gets rendered inside the view via @ChildContent
.
Is there an equivalent for this with ASP.NET Core MVC apps that don't use Blazor? I've spent a few hours researching ViewComponents
, but I can't seem to figure out how my view can access a RenderFragment
on a ViewComponent
.
For instance, a small ViewComponent
I am trying to setup has the following markup:
<div class="card card-px-0 shadow-sm">
<div class="card-header">
<h3 class="card-title">@this.Title</h3>
<div class="card-toolbar">
<button type="button" class="btn btn-sm btn-light">
Action
</button>
</div>
</div>
<div class="card-body">
@ContentTemplate
</div>
<div class="card-footer">
Footer
</div>
</div>
My ViewComponent
is quite basic as well, as the intention here isn't to have it retrieving data - it's meant to be a basic card template (Bootstrap 5), so if Bootstrap 6 changes the structure of a card (like they did with 4 ==> 5, where it's no longer a "portlet"), I fix it in one spot and the hundreds of views I have will automatically get the new structure, vs. changing it everywhere. Here's the ViewComponent:
[ViewComponent(Name = "Card")]
public class CardViewComponent : ViewComponent
{
/// <summary>
/// Gets or sets the card's body
/// </summary>
[Parameter]
public RenderFragment ContentTemplate { get; set; }
/// <summary>
/// Gets or sets card's title
/// </summary>
[Parameter]
public string Title { get; set; }
/// <summary>
/// Invokes this component to render the associated content.
/// </summary>
/// <returns>An IViewComponentResult.</returns>
public IViewComponentResult Invoke()
{
return View("Default");
}
}
I feel like I'm right on the cusp of figuring this out, but just can't quite get there. I've also reviewed the use of a @helper
which is pretty close, but the syntax for a Razor/Blazor app is much cleaner and will let my designer team (who know nothing about .Net) better understand what's happening, e.g.:
<Card Title="Section Title">
<p>I'm the body and would render inside the `ChildContent` RenderFragment!</p>
</Card>
Any suggestions would be much appreciated!