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.
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>