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.
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.
<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.
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
<div class="col-12">
<div class="row">
<RadzenSwitch @bind-Value="@_settingsViewModel.DarkTheme" Style="margin-bottom: 20px" Change="UpdateTheme" />
<span> </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
.
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.
Thanks for reading. Bye!!!
Top comments (0)