Вітаю! Сьогодні ми розглянемо питання, пов’язане зі зміною динамічного атрибуту HTML в рамках додатку Blazor Web Server. Для розв’язання цієї задачі нам знадобиться створити сервіс теми, який буде зчитувати та зберігати значення теми в локальному сховищі та надавати дві властивості: CurrentTheme та ThemeChanged.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class ThemeService { private string _currentTheme = "light"; // тема за замовчуванням public string CurrentTheme { get => _currentTheme; set { if (_currentTheme != value) { _currentTheme = value; ThemeChanged?.Invoke(this, EventArgs.Empty); } } } public event EventHandler ThemeChanged; } |
Усе працює добре, але я не знаю, як знову перерендерити кореневий компонент (App.razor), щоб змінити атрибут data-bs-theme.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
@inject ThemeService ThemeService <!DOCTYPE html> <html dir="rtl" lang="he" data-bs-theme="@ThemeService.CurrentTheme"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <base href="/" /> <link rel="stylesheet" href="app.css" /> <link rel="stylesheet" href="BNWebClient.styles.css" /> <link rel="icon" type="image/png" href="favicon.png" /> <HeadOutlet @rendermode="GlobalRenderSettings.GlobalRenderMode" /> </head> <body> <ThemeLoader @rendermode="GlobalRenderSettings.GlobalRenderMode" /> <Routes /> <script src="_framework/blazor.web.js"></script> php Copy code <script> window.changeTheme = (theme) => { document.documentElement.setAttribute("data-bs-theme", theme) } </script> @code{ [Inject] IJSRuntime JSRuntime { get; set; } csharp Copy code override protected async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { ThemeService.ThemeChanged += async (s, e) => { await InvokeAsync(async () => { await JSRuntime.InvokeVoidAsync("changeTheme", ThemeService.CurrentTheme); }); }; } } } |
Компонент ThemeLoader відповідає за завантаження теми. Якщо поточна тема не дорівнює “light” або “dark”, то використовується файл стилів bootstrap.min.css. В іншому випадку, використовується файл стилів bootstrap-bnext-rtl.min.css.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<HeadContent> @if (!ThemeService.CurrentTheme.Equals("light") && !ThemeService.CurrentTheme.Equals("dark")) { <link rel="stylesheet" href="bootstrap/bootstrap.min.css" /> } else { <link rel="stylesheet" href="bootstrap/bootstrap-bnext-rtl.min.css" /> } </HeadContent> <button @onclick="Toggle">Перемкнути</button> @code { [Inject] IJSRuntime JSRuntime { get; set; } [Inject] ThemeService ThemeService { get; set; } protected override void OnAfterRender(bool firstRender) { if (firstRender) { } base.OnAfterRender(firstRender); } void Toggle() { if (ThemeService.CurrentTheme.Equals("light")) { ThemeService.CurrentTheme = "dark"; } else { ThemeService.CurrentTheme = "light"; } } private async Task HandleThemeChange(string theme) { await JSRuntime.InvokeVoidAsync("changeTheme", theme); } } |