skip to Main Content

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


    • First Thing is preferable to add where is the problem the specific component and class you are referring to within your code.
    • second thing I recommended you to use async/ await I mean use OnInitializedAsync instead of OnInitialized

    for example in your case:

        protected override async Task OnInitializedAsync()
        {
            tempDiceAmounts = await sessionHelper.GetDiceTypeAmmounts();
        }
    

    I added async and i change the void task then use await before your method GetDiceTypeAmmounts

    • in the last : don’t forget to make your function work asynchronously, here how
        public async Task<Ifyou have retrn type> GetDiceTypeAmmounts(){}
    
    Login or Signup to reply.
  1. StateHasChanged(); won’t work in static SSR

    If 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:

    private async Task AddLine()
     {    
        await sessionHelper.AddNewLineAsync();  
         //refresh the page  
         NavigationManager.NavigateTo(NavigationManager.Uri, true);      
    
     }
    

    Here’s a related issue on github:https://github.com/dotnet/aspnetcore/issues/46688

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search