Prevent Server Side Blazor from firing onsubmit in an EditForm

734 Views Asked by At

I would like to prevent Server-Side Blazor from firing the OnSubmit event handler (that I can't get rid of for some other reasons) of the EditForm when I hit Enter in the input field. It seems to be an easy task, and I just can't solve it. I made up the smallest example I could think of:

_Index.razor:

@page "/"
@inject IJSRuntime JSRuntime;


<EditForm Model="Model" OnSubmit="HandleOnSubmit">
    <input id="testInput"/>
    <button type="submit" value="unneeded submit button"></button>
</EditForm>

@code
{
    private CModel Model { get; set; } = new CModel() { ID = "ID", Name = "Name" };

    private async Task HandleOnSubmit()
    {
        await JSRuntime.InvokeAsync<object>("alert", new object[] { "This alert shouldn't be shown!!" });
    }
}

the CModel class (although it has no relevance to the question):

public class CModel
{
    public string ID { get; set; }
    public string Name { get; set; }
}

and the _Host.cshtml:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>PreventSubmitOnForm</title>
    <base href="~/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
</head>
<body>
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>

    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        </environment>
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        </environment>
        <a href="" class="reload">Reload</a>
        <a class="dismiss"></a>
    </div>

    <script src="_framework/blazor.server.js"></script>
    <script>
        document.getElementById("testInput").addEventListener('keypress', function (event) {
            if (event.which === 13) {
                event.preventDefault();
                alert('Form submit prevented');
            }
        });
    </script>
</body>
</html>

In the _Host.cshtml I register a new keypress eventhandler, and as I debug, on page creation it will be really registered. But it never will be triggered on keypress Enter. And I already have tried to trick the situation with @onkeypress:preventDefault and @onkeypress:stopPropagation but they don't seem to help (as Steve Sanderson declared in his issue comment) when I want to prevent the default behavior only for my input field and in that specific field only for the event: Enter pressed.

In a normal HTML + JS case it works like a charm: https://jsfiddle.net/wmk608gh/1/

So I ended up by the JS Interop solution and added the script

<script>
    document.getElementById("testInput").addEventListener('keypress', function (event) {
        if (event.which === 13) {
            event.preventDefault();
            alert('Form submit prevented');
        }
    });
</script>

to the _Host.cshtml. But yet it doesn't seem to work. I presume I'm supposed to register my script to another event (instead of keypress), or maybe there is already a best practice I could follow here.

Any help appreciated.

1

There are 1 best solutions below

0
On BEST ANSWER

The problem is that you try to add the EventListener at a time where your <input /> element is not rendered yet.

To make this work you can call your JS function after blazor has rendered your page:

In your _Index.razor @code block add:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await JSRuntime.InvokeVoidAsync("PreventDefault");
    }
}

In _Host.cshtml wrap your addEventListener with a function:

<script>
    function PreventDefault() {
        document.getElementById("testInput").addEventListener('keypress', function (event) {
            if (event.which === 13) {
                event.preventDefault();
                alert('Form submit prevented');
            }
        });
    }
</script>