4

UPDATED

I have an EditForm component(I missed some non-important stuff, so just to view important pieces of code) , written like this below:

<EditForm Model="@product" OnValidSubmit=@(async () => await SaveProduct())>
  <div class="form-group row">
    <MatPaper Elevation="10" Rounded="true" Style="padding-left: 30px;">
        <div class="col-12 row">
            <label class="col-4 font-weight-bold">Caption:</label>
            <input @ref="firstNameTextBox" class="form-control col-12" @bind="product.Caption" placeholder="Caption" />
            &nbsp;<ValidationMessage For="@(() => product.Caption)" />
        </div>
        <br />
        <div class="col-12 row">
            <label class="col-4 font-weight-bold">Description:</label>
            <InputText class="form-control col-12" @bind-Value="product.Description" placeholder="Description" />
            &nbsp;<ValidationMessage For="@(() => product.Description)" />
        </div>
        <br />
        <div class="col-12 row">
            <label class="col-4 font-weight-bold">Price :</label>
            <InputNumber class="form-control col-12" @bind-Value="product.Price" placeholder="Price" />
            &nbsp;<ValidationMessage For="@(() => product.Price)" />
        </div>

        <div class="form-group row">
            <label for="department" class="col-sm-2 col-form-label">
                Brand:
            </label>
            <div class="col-sm-10">
                <InputSelect id="brandtype" @bind-Value="product.BrandTypeEID" class="form-control">
                    @foreach (var brand in Brands)
                    {
                        <option value="@brand.brandTypeEID">@brand.caption</option>
                    }
                </InputSelect>
            </div>
        </div>


        <br />

        @*<div class="col-12 row">
                <label class="col-4 font-weight-bold">Brand:</label>
                <SelectBrand OnChangeEvent="OnSelectBrandChange"></SelectBrand>
            </div>*@
    </MatPaper>

    <label class="col-2 font-weight-bold"></label>

    <MatPaper Elevation="10" Rounded="true" Style="padding-left: 40px; margin-left: 100px;">
        <label class="col-8 font-weight-bold">
            Categories:
            <CheckBoxList Data="@Categories"
                          TextField="@((item)=>item.Caption)"
                          ValueField="@((item)=>item.CategoryID)"
                          SelectedValues="@SelectedIdsCategory" />
        </label>
    </MatPaper>

    <label class="col-2 font-weight-bold"></label>

    <MatPaper Elevation="10" Rounded="true" Style="padding-left: 30px;">
        <label class="col-2 font-weight-bold"></label>
        <label class="col-2 font-weight-bold">Size types:</label>
        <CheckBoxList Data="@SizeTypes"
                      TextField="@((item)=>item.Caption)"
                      ValueField="@((item)=>item.SizeTypeEID)"
                      SelectedValues="@SelectedIdsSizeType" />
    </MatPaper>
</div>
<br />
<div>
    <h3>Upload PNG images</h3>

    <p>
        <InputFile OnChange="@OnInputFileChange" multiple />
    </p>

    @if (imageDataUrls.Count > 0)
    {
        <h4>Images</h4>

        <div class="card" style="width:30rem;">
            <div class="card-body">
                @foreach (var imageDataUrl in imageDataUrls)
                {
                    <img class="rounded m-1" src="@convertImageToDisplay(imageDataUrl.PictureDisplay)" />
                }
            </div>
        </div>
    }

</div>
<br />

<br />
<div class="col-12 row">
    <span class="col-2"></span>
    <input type="submit" class="form-control col-1 btn btn-primary" @onclick="(() => SaveProduct())" value="Save" />
    <span>&nbsp;</span>
    <input type="submit" class="form-control col-1 btn btn-primary" value="Clear" />
</div>
</EditForm>

And here it is a SaveProduct method:

private async Task SaveProduct()
{
   var productToSave = new ProductForCreationDto();
        
   //some logic 
   if (product.Uid is null)
      await apiCreateProductService.SaveAsync("product/CreateProduct", productToSave);
   else
      await apiCallService.UpdateAsync("product/", product.Uid, product);

   await LoadProducts();

   Result = true;
   IsVisible = true;

   var caption = product.Caption;


   RecordName = caption;

   product = new Product();

        
   await JSRuntime.InvokeVoidAsync("setFocusOnElement", firstNameTextBox);
}

The issue is like the SaveProduct method is called twice, not once. I have 2 same records in database. I think that problem lies on EditForm, but I couldn't get the solution for this problem. What could be a fix?

7
  • 1
    Could you share your button submit code please? Commented Aug 25, 2021 at 12:11
  • Side note: it can be just OnValidSubmit="SaveProduct" Commented Aug 25, 2021 at 13:16
  • 1
    Why do you think it's called twice? Could it be a bug in SaveAsync(() ? Commented Aug 25, 2021 at 13:18
  • You haven't shown the actual submit button in the <EditForm> block. I suspect you're doing something on that. Can you update your code in the question? The code as you've shown us won't call SaveProduct twice. Also forget the (async () => await SaveProduct(). You're creating multiple Task wrappers for nothing. Just call SaveProduct, it returns a Task. Commented Aug 25, 2021 at 14:41
  • @MrCakaShaunCurtis Updated that piece of code, you can review it. Commented Aug 25, 2021 at 17:19

1 Answer 1

3

You have

<EditForm Model="@product" OnValidSubmit=@(async () => await SaveProduct())>

and

<input type="submit" class="..." @onclick="(() => SaveProduct())" value="Save" />

So yes, SaveProduct() will be called twice when you Submit. Both will be called.

The easy fix is to just omit the @onclick and let the EditForm handle it:

<input type="submit" class="..." value="Save" />
Sign up to request clarification or add additional context in comments.

1 Comment

as I said "You haven't shown the actual submit button in the <EditForm> block. I suspect you're doing something on that. " was on the money!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.