NET8 Blazor components and render mode
Asked Answered
S

1

0

I'm creating a Blazor component to have a NuGet package of the design. So, I can use it in different projects. I have a Razor called TopNavBar that displays the header of the page.

<div class="top-navbar style-1">
    <div class="container p-0">
        <div class="row align-items-center">
            <div class="title">
                @Title
            </div>
            <div class="col-lg-4">
                <DarkLightSwitch />
            </div>
        </div>
    </div>
</div>

As you can see, there is another reference to a DarkLightSwitch razor page in the same Blazor component project. This is a simple switch to select a dark mode for the website. If the user clicks on the dark mode, the component has to call a JavaScript function to change the color for the all website.

@inject IJSRuntime jsRuntime

<div class="darkLight-btn">
    <span class="icon @(IsDarkTheme ? "" : "active")" 
        id="light-icon" @onclick="OnLightClick">
        <i class="la la-sun"></i>
    </span>
    <span class="icon @(IsDarkTheme ? "active" : "")" 
        id="dark-icon" @onclick="OnDarkClick">
        <i class="la la-moon"></i>
    </span>
</div>

@code {
    /// <summary>
    /// Is the dark theme activate?
    /// </summary>
    [Parameter] public bool IsDarkTheme { get; set; } = false;

    protected async Task OnLightClick(MouseEventArgs args)
    {
        await jsRuntime.InvokeVoidAsync("switchToLight");
        IsDarkTheme = false;
    }

    protected async Task OnDarkClick(MouseEventArgs args)
    {
        await jsRuntime.InvokeVoidAsync("switchToDark");
        IsDarkTheme = true;
    }
}

When I add the TopNavBar to a MainLayout.razor or any other page, if I click on the DarkLightSwitch nothing is happening because the page is rendered in a static mode.

If in the TopNavBar I call the DarkLightSwitch like this

<DarkLightSwitch @rendermode="RenderMode.InteractiveAuto" />

at run-time the component is not be found.

![enter image description here](/api/attachments/8f0b79cd-20e0-4b8e-8e65-90aed165d925?platform=QnA)

If I add the @rendermode to the TopNavBar, the entire Razor page is not found.

Is there a way to fix it?

Severus answered 12/12, 2023 at 12:8 Comment(1)
As you made it Auto it needs to run both on server and client. Put the component in the client. The server can see the clients components not the other way around...Gametophyte
C
1

I'm making some [major] assumptions based on your description:

You have built a Net8 solution using the Blazor Web App template with InteractiveAuto and Per page/component options selected. You have a third Razor Class Library project containing the components you want to put in a Nuget package.

Here's my version of your DarkLightSwitch. Note mutating parameters within a component is a NONO. I'm assuming IsDarkTheme is the default starting theme, so I've named it as such and only check it on start up to set the internal field.

@inject IJSRuntime JsRuntime

<div>
    <button class="@_buttonCss" @onclick="this.OnClickAsync">@_buttonText</button>
</div>

@code {
    // Allow the parameter to be null if it's not set.
    // You should never set it in code
    [Parameter] public bool IsDefaultDarkTheme { get; set; } = true;

    private bool _isDark;
    private bool _isInitialised;
    private string _buttonCss => _isDark ? "btn btn-light" : "btn btn-dark";
    private string _buttonText => _isDark ? "Switch To Light" : "Switch To Dark";

    public override Task SetParametersAsync(ParameterView parameters)
    {
        parameters.SetParameterProperties(this);

        if (!_isInitialised)
        {
            // only updates if the parameter has a value
            _isDark = this.IsDefaultDarkTheme;
            _isInitialised = true;
        }

        return base.SetParametersAsync(ParameterView.Empty);
    }

    private async Task OnClickAsync()
    {
        if (await JsRuntime.InvokeAsync<bool>("confirm", "Are you sure?"))
            _isDark = !_isDark;
    }
}

This library needs to be referenced by both the Server and Client projects.

MainLayout in the Server project looks like this:

@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <ComponentLibrary.DarkLightSwitch @rendermode="InteractiveAuto" />
            <a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

<div id="blazor-error-ui">
    An unhandled error has occurred.
    <a href="" class="reload">Reload</a>
    <a class="dismiss">🗙</a>
</div>

There's a temporary Repo here.

enter image description here

Celinacelinda answered 12/12, 2023 at 18:59 Comment(1)
Thank you so much for your code and your repo.Severus

© 2022 - 2024 — McMap. All rights reserved.