cbalakus
cbalakus

Reputation: 630

How can I reach body tag or another tag from Razor Page in Blazor WebAssembly?

I'm trying to reach to body from a Razor page. I have just started to learn Blazor. So I don't know if it is possible or not. Basically I'm trying to change the body class from the C# side and from different pages. I can do it with JavaScript but I want to do it with Blazor WebAssembly. It can work if the body is inside of the Razor page. But I don't want to use it that way.

index.html:

<!DOCTYPE html>
<html lang="tr">
<head>
    <meta charset="utf-8" />
</head>
<body class="theme-dark">
    <app>Loading...</app>
    <script src="_framework/blazor.webassembly.js"></script>
</body>
</html>

MainLayout.razor:

@inherits LayoutComponentBase
<div class="grid-wrapper sidebar-bg bg1">
    <div id="theme-tab">
        <div class="theme-tab-item switch-theme bg-white" @onclick="ToggleTheme" data-theme="theme-default" title="Light"></div>
        <div class="theme-tab-item switch-theme bg-dark" @onclick="ToggleTheme" data-theme="theme-dark" title="Dark"></div>
    </div>
    <NavMenu />
    <SideBar />
    <div class="main">
        @Body
    </div>
    <Footer />
</div>

@code {
    private bool isDark = true;
    private string currentTheme => isDark ? "theme-dark" : "theme-default"; //I want to use this variable in other pages.

    private void ToggleTheme()
    {
        isDark = !isDark;
    }
}

Upvotes: 3

Views: 3360

Answers (2)

FarrukhMalik
FarrukhMalik

Reputation: 177

Wrap your Layout HTML in a <body> tag.

I needed the navbar-collapsed class in the <body> in some layouts and navbar-expand in some layouts. By default it was navbar-expand so in the other layout where I needed collapsed I just wrapped my layout HTML in a <body> tag with class="navbar-collapsed" and it worked.

Upvotes: 0

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30167

If you want to change out the <body> class

Add a JS file.

site.js

window.SetBodyCss = function (elementId, classname) {
    var link = document.getElementById(elementId);
    if (link !== undefined) {
        link.className = classname;
    }
    return true;
}

Reference it in Host.cshtml.
Create an id on <body>.

<body id="BlazorMainBody">

    <script src="/site.js"></script>
    <script src="_framework/blazor.server.js"></script>
</body>

Add a helper class

using Microsoft.JSInterop;
using System.Threading.Tasks;

namespace Blazor.Starter
{
    public class AppJsInterop
    {
        protected IJSRuntime JSRuntime { get; }

        public AppJsInterop(IJSRuntime jsRuntime)
        {
            JSRuntime = jsRuntime;
        }

        public ValueTask<bool> SetBodyCss(string elementId, string cssClass)
          => JSRuntime.InvokeAsync<bool>("SetBodyCss", elementId, cssClass);
    }
}

This shows toggling it in a page

<button type="button" @onclick="SetCss">SetCss</button>

@code {
    [Inject] private IJSRuntime _js { get; set; }

    private bool _isbodyCss;

    private string _bodyCss => _isbodyCss ? "Theme-Dark" : "Theme-Light";

    private async Task SetCss()
    {
        var appJsInterop = new AppJsInterop(_js);
        await appJsInterop.SetBodyCss("BlazorMainBody", _bodyCss);
        _isbodyCss = !_isbodyCss;
    }
}

You can change out the whole stylesheet in a similar way - see this note of mine

Upvotes: 4

Related Questions