Search code examples
blazorblazor-webassemblysyncfusion

Blazor: OnValidSubmit fired when a button is pressed inside an EditForm


I have an EditForm that contains a button used to open a popup. I found out that as soon as I click on the button, the function specified in OnValidSubmit gets called.

This only happens if the button that opens the popup is placed inside the form. If I place it outside, the function is not called.

The function specified in OnValidSubmit must be called only when I click on the submit button.

This is a stripped down test page:

@page "/testpage"

<h3>Test Page</h3>

<EditForm Model="mdl" OnValidSubmit="Save">
    <div class="form-container" style="border:1px solid 0">
        <FluentValidationValidator />
        <ValidationSummary />

        <InputText @bind-Value="mdl.Prop1"></InputText>

        <button @onclick="OpenPopup">Open popup (within form)</button>

    </div>

    <button type="submit">Save</button>

</EditForm>

<button @onclick="OpenPopup">Open popup (outside form)</button>

<TestDialog @bind-Visible="isDlgVisible" OnDlgClosed="OnDialogClose" OnDlgSetValue="OnDialogSetValue"></TestDialog>

@code {

    private MyModel mdl = new();

    private bool isDlgVisible = false;

    private void OpenPopup()
    {
        isDlgVisible = true;
    }

    private void OnDialogSetValue(string v)
    {
        // ... Here I will use the value selected through the popup ...
    }

    private void OnDialogClose()
    {
        isDlgVisible = false;
    }

    private void Save()
    {
        // This function is called as soon as I click on the "Open popup (within form)" button.
        Console.WriteLine("Save!");
    }

    class MyModel
    {
        public string Prop1 { get; set; }
    }

}

And this is the popup component:

<SfDialog IsModal="true" Width="200px" ShowCloseIcon="true" @bind-Visible="Visible" CssClass="mydialog">

    <DialogEvents Closed="OnDlgClosed"></DialogEvents>
    <DialogTemplates>
        <Header>Test Popup</Header>
        <Content>
            <button @onclick="SetAndClose">Set and close</button>
        </Content>
    </DialogTemplates>
</SfDialog>

@code {

    [Parameter] public bool Visible { get; set; }
    [Parameter] public EventCallback<CloseEventArgs> OnDlgClosed { get; set; }
    [Parameter] public Action<string> OnDlgSetValue { get; set; }

    // Blazor gives an error if I don't declare this property, even if it's not used anywhere...
    [Parameter] public EventCallback<bool> VisibleChanged { get; set; }

    private void SetAndClose()
    {
        if (OnDlgSetValue != null)
        {
            OnDlgSetValue.Invoke("Set through popup.");
        }
        Visible = false;
    }

}   

Solution

  • Add type="button" to the button that opens the modal:

    <button type="button" @onclick="OpenPopup">Open popup (within form)</button>
    

    This is because when the type attribute is not specified the default value is submit for buttons inside forms.

    https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type

    If that doesn't work, you can add @onclick:preventDefault to the button to prevent the form submit:

    <button @onclick="OpenPopup" @onclick:preventDefault>Open popup (within form)</button>
    

    https://learn.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-6.0#prevent-default-actions