I am currently experimenting with Blazor 8 SSR. I would like to create Sample App for throwing dices.
In one Blazor Page I have multiple forms (for example for adding and deleting additional dices) and one form to roll them.
The form to roll the dices is dependent on the other forms for configuring the amount of dices the user wants to throw. So when a form for configuring the dices is fired, the main form should afterwards get how many dices must be thrown. I load that information on OnInitialized
.
Sadly, the OnInitialized
method of the forms are fired always BEFORE the submit method of the other forms, so I have no posibility of getting the data that has just been posted.
For example: In this component I can add new dices:
@using DiceMaster.Lib.Helpers
@inject SessionHelper sessionHelper
<h3>DiceAmountConfigurator</h3>
@foreach (TempDiceAmount line in lines)
{
<DiceAmountLine line="line"></DiceAmountLine>
}
<form method="post" @onsubmit="AddLine" @formname="AddLine">
<AntiforgeryToken />
<button type="submit">Add</button>
</form>
@code {
private List<TempDiceAmount> lines { get; set; } = new();
protected override void OnInitialized()
{
lines = sessionHelper.GetDiceTypeAmmounts();
}
private void AddLine()
{
sessionHelper.AddNewLine();
lines = sessionHelper.GetDiceTypeAmmounts();
StateHasChanged();
}
}
And this is the form for throwing the dices:
@using DiceMaster.Lib.Dices
@using System.ComponentModel
@using DiceMaster.Lib.Helpers
@using Microsoft.Extensions.Primitives
@inject IHttpContextAccessor httpContextAccessor
@inject SessionHelper sessionHelper
<EditForm Enhance Model="@formData" OnValidSubmit="@RollDices" FormName="DiceRoller">
@{
int index = 0;
}
@foreach (TempDiceAmount am in tempDiceAmounts)
{
<input type="hidden" value="@am.DiceTypeId" name="formData.Amounts[@index].DiceTypeId"/>
<input type="hidden" value="@am.Count" name="formData.Amounts[@index].DiceCount"/>
index++;
}
<button type="submit">Roll</button>
</EditForm>
@if (rollResults.Count > 0)
{
@foreach (var result in rollResults)
{
<div>@result.Value</div>
}
}
@code {
[SupplyParameterFromForm(FormName = "DiceRoller")]
public RoleDiceFormInfo formData { get; set; } = new RoleDiceFormInfo();
private DiceTypeGetter diceTypeGetter { get; set; } = new DiceTypeGetter();
private List<DiceRollResult> rollResults { get; set; } = new List<DiceRollResult>();
private List<TempDiceAmount> tempDiceAmounts { get; set; } = new List<TempDiceAmount>();
protected override void OnInitialized()
{
tempDiceAmounts = sessionHelper.GetDiceTypeAmmounts();
}
protected override void OnParametersSet()
{
tempDiceAmounts = sessionHelper.GetDiceTypeAmmounts();
}
protected override void OnAfterRender(bool firstRender)
{
tempDiceAmounts = sessionHelper.GetDiceTypeAmmounts();
}
private void RollDices()
{
DiceRoller roller = new DiceRoller();
DiceRollRequest request = new DiceRollRequest();
request.DiceAmmounts = new List<DiceTypeAmmount>();
request.DiceAmmounts.AddRange(formData.Amounts);
List<DiceRollResult> results = roller.RollDices(request);
rollResults = results;
}
public class RoleDiceFormInfo
{
public List<DiceTypeAmmount> Amounts { get; set; }
}
}
On the second Form, all methods (OnInitialized and OnParameterSet, OnAfterRender is not called at all because of SSR) are called before the Submit of the first Form, so the component does not get the newest information.
As a summary:
this function in the first component
private void AddLine()
{
sessionHelper.AddNewLine();
lines = sessionHelper.GetDiceTypeAmmounts();
StateHasChanged();
}
is called after the onInitialized function of the second component:
protected override void OnInitialized()
{
tempDiceAmounts = sessionHelper.GetDiceTypeAmmounts();
}
How could I handle this situation?
The project can be found here:
https://github.com/Maera90/DiceMaster
2
Answers
OnInitializedAsync
instead ofOnInitialized
for example in your case:
I added async and i change the void task then use await before your method
GetDiceTypeAmmounts
StateHasChanged();
won’t work in static SSRIf you want to update the content in your page,you have to refresh your whole page,you wouldn’t be able to call js to update part of the page due to in static ssr either.
You could try inject NavigationManager ,and call:
Here’s a related issue on github:https://github.com/dotnet/aspnetcore/issues/46688