How to change theme at runtime
Description
You may want to change the Telerik Blazor Theme during runtime on the fly - for example, to allow your users to choose the application theme.
This article will explain how you can do this. The approach will apply both to the built-in themes, and to custom themes.
The stylesheets are registered outside of the <app>
element so normal Blazor code cannot access them. This leaves only JS Interop as the option to change the themes.
Solution
To change a theme, you must:
- Create a
<link>
element pointing to the new theme - Remove the old
<link>
that pointed to the previous theme when the new one loads
Here is a basic implementation:
Step 1 - Index file - this is a sample from a Server app, replace the URL with the one you are actually using. The important bit is the id
attribute that lets us get the element easily
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Blazor App</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<!-- Theme switching start -->
<link id="TelerikThemeLink" rel="stylesheet" href="https://blazor.cdn.telerik.com/blazor/4.5.0/kendo-theme-default/all.css" />
<script src="~/ThemeChanger.js"></script>
<!-- Theme switching end -->
<script src="_content/Telerik.UI.for.Blazor/js/telerik-blazor.js" defer></script>
</head>
Step 2 - Prepare JS Interop function that will switch out the <link>
elements
// this code is in the ~/wwwroot/ThemeChanger.js file
var themeChanger = {
changeCss: function (cssFileUrl) {
var oldLink = document.getElementById("TelerikThemeLink"); // we have this id on the <link> that references the theme
if (cssFileUrl === oldLink.getAttribute("href")) {
return;
}
var newLink = document.createElement("link");
newLink.setAttribute("id", "TelerikThemeLink");
newLink.setAttribute("rel", "stylesheet");
newLink.setAttribute("type", "text/css");
newLink.setAttribute("href", cssFileUrl);
newLink.onload = () => {
oldLink.parentElement.removeChild(oldLink);
};
document.getElementsByTagName("head")[0].appendChild(newLink);
}
}
Step 3 - Call the JS Interop function from your Blazor code and pass the new theme URL. In this example we switch from Default to Material built-in theme.
@inject IJSRuntime JsInterop
<TelerikButton OnClick="ChangeTheme">Change from Default to Material Built-in Theme</TelerikButton>
@code {
async Task ChangeTheme()
{
// use the new URL you will use - it can be relative and/or point to a custom theme
string newThemeUrl = "https://blazor.cdn.telerik.com/blazor/4.5.0/kendo-theme-material/all.css";
// call the JS interop that will switch out the <link> element
await JsInterop.InvokeVoidAsync("themeChanger.changeCss", new[] { newThemeUrl });
}
}