I have Blazor WebAssembly application. I have a parent and child component that share a model class. When the child updates a value on the model, the child redraws itself, but the parent does not. So what exactly triggers a Blazor component to redraw itself? I can't find any documentation on this particular aspect of Blazor.
I have an POCO model class. In the real application this comes from a separate assembly. Models/AwesomenessModel.cs:
namespace BlazorApp.Models {
public class AwesomenessModel {
public int? Level { get; set; }
}
}
My index page. Pages/Index.razor:
@page "/"
@using BlazorApp.Components
@using BlazorApp.Models
<Awesomeness AwesomenessModel="@AwesomenessModel"></Awesomeness>
@code {
private AwesomenessModel AwesomenessModel = new AwesomenessModel();
}
The parent class. I have added a redraw button to verify that the content should have changed. Components/Awesomeness.razor:
@using BlazorApp.Models
@if (AwesomenessModel.Level.HasValue) {
<div>Awesomeness is @AwesomenessModel.Level.Value</div>
} else {
for (int i = 0; i < 10; i++) {
<AwesomenessSelector AwesomenessModel="@AwesomenessModel" Level="@i"></AwesomenessSelector>
}
}
<div><button class="btn btn-link" @onclick="RedrawClick">Redraw</button></div>
@code {
[Parameter]
public AwesomenessModel AwesomenessModel { get; set; }
private void RedrawClick() {
this.StateHasChanged();
}
}
The child component that does the actual change to the Awesomeness model. Components/AwesomenessSelector.razor:
@using BlazorApp.Models
@if (!AwesomenessModel.Level.HasValue) {
<div><button class="btn btn-link" @onclick="LevelClick">@Level</button></div>
}
@code {
[Parameter]
public AwesomenessModel AwesomenessModel { get; set; }
[Parameter]
public int Level { get; set; }
private void LevelClick() {
AwesomenessModel.Level = Level;
}
}
When I run the application and click on an awesomeness level, that level disappears (the AwesomenessSelector component redraws), but the rest are still visible and there is no 'Awesomeness is...' message (the Awesomeness component does not update). If I then click the Redraw button to force the Awesomeness component to redraw, I get the correct 'Awesomeness is...' message.
I'm probably not structuring the code in the correct way to get the parent component to redraw automatically. How should I structure it in this scenario?
Child Component add a EventCallback for OnLevelClick
@using BlazorApp.Models
@if (!AwesomenessModel.Level.HasValue) {
<div><button class="btn btn-link" @onclick="LevelClick">@Level</button></div>
}
@code {
[Parameter]
public AwesomenessModel AwesomenessModel { get; set; }
[Parameter]
public int Level { get; set; }
[Parameter]
public EventCallback<string> OnLevelClick { get; set; }
private void LevelClick() {
AwesomenessModel.Level = Level;
OnLevelClick.InvokeAsync();
}
}
parent Component add Handler for OnLevelClick
@using BlazorApp.Models
@if (AwesomenessModel.Level.HasValue) {
<div>Awesomeness is @AwesomenessModel.Level.Value</div>
} else {
for (int i = 0; i < 10; i++) {
<AwesomenessSelector AwesomenessModel="@AwesomenessModel" Level="@i" @OnLevelClick="OnLevelClick"></AwesomenessSelector>
}
}
@code {
[Parameter]
public AwesomenessModel AwesomenessModel { get; set; }
private void OnLevelClick() {
this.StateHasChanged();
}
}
hope this helps