How to figure out that is first loading of page or form submitting in .net 8 Blazor SSR

130 Views Asked by At

I have a page that do both add and edit Commodities named CommodityAddEdit component. When we are in edit mode the Id is not null so we can figure out that we are in edit mode. In OnInitializedAsync() method I fill Model (vm) of EditForm. But after click on submit button the OnInitializedAsync() method executes too and vm fill again from database value record. How to figure out that we are filling form first time or we are in posting form mode in OnInitializedAsync() method?

<EditForm Model="@vm" OnSubmit="Submit" FormName="CommodityAddEdit"
          method="post" enctype="multipart/form-data" Enhance>

[SupplyParameterFromForm]
private AddEditCommodityVm vm { get; set; } = new();

protected override async Task OnInitializedAsync()
{
    if (Id is not null) // update
    {
        var commodity = await appDbContext.Commodities.FindAsync(Id);
        if (vm.Title.Length == 0) // Load form data first time
            vm = commodity!.Adapt<AddEditCommodityVm>();
    }
}

public async Task Submit(EditContext editContext)
{
    if (Id == null)
        await Add(editContext);
    else
        await Update(editContext);
}

The if condition is wrong because maybe the user send empty fields.

2

There are 2 best solutions below

1
Calango On

As said in this post, you need to put on the top of your component:

@rendermode RenderMode.InteractiveAuto

With that, your OnInitializedAsync will enter only once.

0
M Komaei On

Finally I did myself. I added a hidden input in EditForm and a bool property in vm named LoadForm with true default value and bind the hidden input to this property. Boolean default value is false and after creating the vm object the LoadForm become true and we can figure out that the vm is created and we are in loading mode of component and not in submit form mode.

<input type="hidden" @bind-value="vm.LoadForm" />

public class AddCommodityVm
{
    public bool LoadForm { get; set; } = true;

    [Required, Length(2, 50, ErrorMessage = Constants.LengthMsg)]
    public string Title { get; set; } = "";

    public IFormFile? PdfFile { get; set; }
}

protected override async Task OnInitializedAsync()
{
    Industries = await appDbContext.Industries.AsNoTracking().ToListAsync();
    if (Id is not null && vm.LoadForm) // update : fill form
    {
        var commodity = await appDbContext.Commodities.FindAsync(Id);
        vm = commodity!.Adapt<AddCommodityVm>();
    }
}

<EditForm Model="@vm" OnSubmit="Submit" FormName="CommodityAddEdit"
          method="post" enctype="multipart/form-data" Enhance>
    <input type="hidden" @bind-value="vm.LoadForm" />
    <DataAnnotationsValidator />

            @* Title *@
            <div class="form-floating mb-3">
                <InputText @bind-Value="vm.Title" class="form-control" placeholder autofocus />
                <label>Title</label>
                <ValidationMessage For="() => vm.Title" class="text-danger" />
                @if (ShowAlert == true)
                {
                    <Alert Text="@AlertText" />
                }
            </div>

            @* PdfFile *@
            <div class="mb-3">
                <label>Pdf File</label>
                <label style="color:gray">@(vm.PdfName!=null ? $" (Now is : {vm.PdfName})": "")</label>
                <InputFile accept=".pdf" name="vm.PdfFile" class="form-control" placeholder />
                <ValidationMessage For="() => vm.PdfFile" class="text-danger" />
            </div>                    

            @* Submit button *@
            <div class="d-flex justify-content-center mt-3">
                <button type="submit" class="btn btn-outline-success w-50">
                    Submit
                </button>                    
            </div>

</EditForm>

Another solution without using hidden input. Just check HttpContext.Request.Method type for GET or POST string value. First inject IHttpContextAccessor to the _Imports.razor file then use it in c# file. When form post to the server the value is POST and when the page is opening the value is GET.

@inject IHttpContextAccessor HttpContextAccessor

protected override async Task OnInitializedAsync()
{
    if (Id is not null && HttpContextAccessor.HttpContext!.Request.Method == "GET")
    {
        var commodityPrice = await appDbContext.CommodityPrices.FindAsync(Id);
        vm = commodityPrice!.Adapt<AddEditCommodityPriceVm>();
    }
}