Reputation: 128
I have the following code in a Blazor component:
protected override async Task OnInitializedAsync()
{
appBarState.Title = "Analyses";
project = await ApiService.GetFromJsonAsync<ProjectDTO>($"api/Projects/{ProjId}/dto");
// TODO: Not working
appBarState.Title = $"Analyses for project {project?.Name}";
Console.WriteLine($"Analyses for project {project?.Name}");
}
The intention is to set the top app bar with a default title, call the API to get more information about the object, and update the app bar with more accurate information using the shared AppBarState
class below.
public class AppBarState
{
public string Title { get; set; }
}
The app bar title is set to Analyses
, the API is called and the correct value is returned. The Console.WriteLine
line for $"Analyses for project {project?.Name}"
works correctly, however trying to update the shared state with this value is not successful. The app bar title remains as Analyses
, not even Analyses for project
.
I'm assuming the issue is with updating shared state after an await
call as trying to update the app bar state after the await
call with any value (plain string without referencing project
) fails to update.
Upvotes: 0
Views: 1586
Reputation: 30340
I'm making the assumption that you are displaying the title in a different component or in the layout.
Add an event and a setter to AppBarState and register it as a Scoped DI service:
public class AppBarState
{
public event EventHandler? TitleChanged;
public string? Title { get; private set; }
public void SetTitle(string title)
{
this.Title = title;
this.NotifyTitleChanged();
}
public void NotifyTitleChanged()
=> this.TitleChanged?.Invoke(this, EventArgs.Empty);
}
Program:
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddScoped<AppBarState>();
Here's a component to display the title:
@inject AppBarState appBarState
@implements IDisposable
<h3>@this.appBarState.Title</h3>
@code {
protected override void OnInitialized()
=> appBarState.TitleChanged += this.OnTitleChanged;
// Kick off a re-redner event on the component
private void OnTitleChanged(object? sender, EventArgs e)
=> this.InvokeAsync(this.StateHasChanged);
public void Dispose()
=> appBarState.TitleChanged -= this.OnTitleChanged;
}
Here's a test page to show it working:
@page "/"
@inject AppBarState appBarState;
<h1>Hello</h1>
<TitleBar />
@code {
protected override async Task OnInitializedAsync()
{
appBarState.SetTitle("Loading");
// Emulate an async data get
await Task.Delay(2000);
appBarState.SetTitle($"Loaded at {DateTime.Now.ToLongTimeString()} ");
}
}
Upvotes: 1
Reputation: 197
You need to call
StateHasChanged()
after updating the value of title
Upvotes: 1