My application is built with .NET 8 in Blazor. The configuration in the Program.cs
is like this:
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
I want to have a nice sidebar for it. I created a SidebarComponent
that generates the sidebar quite nicely. This is the code of the component
@inject NavigationManager _navigationManager
@rendermode InteractiveAuto
<aside id="sidebar" class="sidebar break-point-sm has-bg-image @(_isCollapsed ? "collapsed" : "") @(_isToggled ? "toggled" : "")">
<a @onclick="BtnCollapseClicked" id="btn-collapse" class="sidebar-collapser"><i class="ri-arrow-left-s-line"></i></a>
<div class="image-wrapper">
</div>
<div class="sidebar-layout">
<div class="sidebar-header">
<div class="pro-sidebar-logo">
<div>P</div>
<h5>Pro Sidebar</h5>
</div>
</div>
<div class="sidebar-content">
<nav class="menu open-current-submenu">
<ul>
<li class="menu-header"><span>BLAZOR</span></li>
@foreach (var menuItem in standardItems)
{
<MenuItemComponent MenuItem="@menuItem" MenuItemClickCallback="MenuItemClick" />
}
</ul>
</nav>
</div>
</div>
</aside>
@code {
private bool _isCollapsed { get; set; } = false;
private bool _isToggled { get; set; } = false;
List<MenuItem> standardItems = SidebarData.GetStandardMenuItems();
List<MenuItem> generalMenuItems = SidebarData.GetGeneralMenuItems();
public void BtnToggleClicked()
{
_isToggled = !_isToggled;
StateHasChanged();
}
public void MouseClickedInOverlay()
{
if (_isToggled)
_isToggled = false;
generalMenuItems.ForEach(x => x.IsOpened = false);
StateHasChanged();
}
// Omitted
}
Then in the MainLayout
, I added
<div class="layout has-sidebar fixed-sidebar fixed-header">
<SidebarComponent @ref="sideBarComponent"/>
<div @onclick="@(e => sideBarComponent?.MouseClickedInOverlay())" id="overlay" class="overlay"></div>
<div class="layout">
<!-- Omitted -->
</div>
</div>
When the application starts, I get this error:
System.InvalidCastException: 'Unable to cast object of type 'Microsoft.AspNetCore.Components.Endpoints.SSRRenderModeBoundary' to type 'HypnoPlatform.Client.Pages.Shared.Sidebar.SidebarComponent'.'
How can I call methods from the MainLayout
to the SidebarComponent
?
I recall stumbling into this previously. I think the issue is that the line:
<SidebarComponent @ref="sideBarComponent"/>
is, unintuitively, trying to assign an SSRRenderModeBoundary to the variable sideBarComponent, instead of a SidebarComponent. Something to do with the framework wrapping the component with SSRRenderModeBounday when using InteractiveAuto.
I never really got to the bottom of it, but using a shared service to communicate was my solution. Something like:
public class SidebarStateService
{
public event Action? OnOverlayClicked;
public void OverlayClicked()
{
OnOverlayClicked?.Invoke();
}
}
Then inject this into both your MainLayout and Sidebar.
Call OverlayClicked from MainLayout and hookup to OnOverlayClicked in your Sidebar.,