Blazor WebAssembly : Dark/Light Theme Switch
Tags: blazor, dotnet, aspnetcore, themes
Published: 2021-05-30 09:11:17

Some people like dark theme and some like light theme. I implemented a switch for Blazor WebAssembly apps so that user can switch between dark and light themes. 

[Source code : BlazingChat] (https://github.com/CuriousDrive/BlazingChat)

For this demo, I created two CSS files for light and dark themes. `app-light.css` will be the default theme for the application and `app-dark.css` is the dark theme of the application. Please check the code below.

```html
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>BlazingChat</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
    <link id="theme" href="css/app-light.css" rel="stylesheet" />
    <!-- <link id="theme" href="css/app-dark.css" rel="stylesheet" /> -->
    <link href="manifest.json" rel="manifest" />
</head>
```

I've added references in the `index.html` file in head tag the Blazor WebAssembly app. I've made sure to set the `id` of these links so that we could find these links and add and remove them from our JavaScript function 

That's what we're trying to do in below JavaScript function. I namesd this function as `setTheme` which takes `themeName` as a parameter. I am adding a CSS `link` and removing the old theme which was set for the application. Please check the code below.

```javascript
export function setTheme(themeName) {

    //add a new css link
    let newLink = document.createElement("link");
    newLink.setAttribute("id", "theme");
    newLink.setAttribute("rel", "stylesheet");
    newLink.setAttribute("type", "text/css");
    newLink.setAttribute("href", `css/app-${themeName}.css`);
    //remove the theme from the head tag
    let head = document.getElementsByTagName("head")[0];
    head.querySelector("#theme").remove();
    //adding newLink in the head
    head.appendChild(newLink);
}
```
We can call this JavaScript function from our Razor component and we should be able to change the theme of our application right away. I am using JavaScript Isolation to make this call. Please check the code for `Settings.razor` component

```c#
<div class="col-12">
    <div class="row">
        <RadzenSwitch @bind-Value="@_settingsViewModel.DarkTheme" Style="margin-bottom: 20px" Change="UpdateTheme" />
        <span>&nbsp; &nbsp;</span>
        <label class="white-text"> Dark Theme </label>    
    </div>
</div>

@code {
private async Task UpdateTheme()
{
        //setting the themeName parameter
        var themeName = _settingsViewModel.DarkTheme ? "dark" : "light";
        //calling JS function
        var module = await _jsRuntime.InvokeAsync<IJSObjectReference>("import","./js/site.js");
        await module.InvokeVoidAsync("setTheme", themeName);
        //persisting the settings in DB
        await _settingsViewModel.UpdateTheme();
}
```

This approach has one issue though, if I refresh the application then it doesn't matter which theme that the user has set it is going to set the default theme for the application, which is the light theme in this case.

To fix this issue I needed to persist the current theme somewhere. I did that in the user table that I have created in SQLite. I got the current authenticated user whenever `MainLayout.razor` gets initialized. and called the same JavaScript function to set the theme of the application. That way, whenever I refresh the application I don't lose the current theme. Please check the code below for `OnInitializedAsync` event for `MainLayout.razor`.

```c#
protected override async Task OnInitializedAsync()
{
        //getting the current authenticated user for the app
        User currentUser = await _httpClient.GetFromJsonAsync<User>("user/getcurrentuser");
        if(currentUser != null)
        {
            //setting the themeName parameter for JS function
            var themeName = currentUser.DarkTheme == 1 ? "dark" : "light";
            //calling the JS function
            var module = await _jsRuntime.InvokeAsync<IJSObjectReference>("import","./js/site.js");
            await module.InvokeVoidAsync("setTheme", themeName);
        }
        await base.OnInitializedAsync();
}
```

If you like watching video tutorial of this blog then please click on the video below.
[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/5qRaUviEYIw/0.jpg)](https://www.youtube.com/watch?v=5qRaUviEYIw)

Thanks for reading. Bye!!!