preventDefault for form onsubmit handlers. Fixes #951
This commit is contained in:
parent
79c60c91af
commit
4aaeac1e51
|
|
@ -8,6 +8,7 @@ import { applyCaptureIdToElement } from './ElementReferenceCapture';
|
|||
const selectValuePropname = '_blazorSelectValue';
|
||||
const sharedTemplateElemForParsing = document.createElement('template');
|
||||
const sharedSvgElemForParsing = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||
const preventDefaultEvents: { [eventType: string]: boolean } = { submit: true };
|
||||
let raiseEventMethod: MethodHandle;
|
||||
let renderComponentMethod: MethodHandle;
|
||||
|
||||
|
|
@ -354,7 +355,11 @@ function countDescendantFrames(batch: RenderBatch, frame: RenderTreeFrame): numb
|
|||
}
|
||||
}
|
||||
|
||||
async function raiseEvent(event: Event, browserRendererId: number, componentId: number, eventHandlerId: number, eventArgs: EventForDotNet<UIEventArgs>) {
|
||||
function raiseEvent(event: Event, browserRendererId: number, componentId: number, eventHandlerId: number, eventArgs: EventForDotNet<UIEventArgs>) {
|
||||
if (preventDefaultEvents[event.type]) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
const eventDescriptor = {
|
||||
browserRendererId,
|
||||
componentId,
|
||||
|
|
@ -362,7 +367,7 @@ async function raiseEvent(event: Event, browserRendererId: number, componentId:
|
|||
eventArgsType: eventArgs.type
|
||||
};
|
||||
|
||||
await DotNet.invokeMethodAsync(
|
||||
return DotNet.invokeMethodAsync(
|
||||
'Microsoft.AspNetCore.Blazor.Browser',
|
||||
'DispatchEvent',
|
||||
eventDescriptor,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure;
|
|||
using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure.ServerFixtures;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
using OpenQA.Selenium.Support.UI;
|
||||
using System;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
|
|
@ -108,5 +110,22 @@ namespace Microsoft.AspNetCore.Blazor.E2ETest.Tests
|
|||
actions.Perform();
|
||||
WaitAssert.Equal("onmousedown,onmouseup,", () => output.Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PreventDefault_AppliesToFormOnSubmitHandlers()
|
||||
{
|
||||
var appElement = MountTestComponent<EventPreventDefaultComponent>();
|
||||
|
||||
appElement.FindElement(By.Id("form-1-button")).Click();
|
||||
WaitAssert.Equal("Event was handled", () => appElement.FindElement(By.Id("event-handled")).Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PreventDefault_DotNotApplyByDefault()
|
||||
{
|
||||
var appElement = MountTestComponent<EventPreventDefaultComponent>();
|
||||
appElement.FindElement(By.Id("form-2-button")).Click();
|
||||
Assert.Contains("about:blank", Browser.Url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
<h3>Prevent default</h3>
|
||||
|
||||
<p>
|
||||
Currently we don't call <code>preventDefault</code> by default on DOM events in most cases.
|
||||
The one exception is for form submit events: in that case, if you have a C# onsubmit handler,
|
||||
you almost certainly don't really want to perform a server-side post, especially given that
|
||||
it would occur <em>before</em> an async event handler.
|
||||
</p>
|
||||
<p>
|
||||
Later, it's likely that we'll add a syntax for controlling whether any given event handler
|
||||
triggers a synchronous <code>preventDefault</code> before the event handler runs.
|
||||
</p>
|
||||
|
||||
<h2>Form with onsubmit handler</h2>
|
||||
|
||||
<form action="about:blank" onsubmit=@(() => { })>
|
||||
<button id="form-1-button" onclick=@HandleClick>Click me</button>
|
||||
</form>
|
||||
|
||||
<h2>Form without onsubmit handler</h2>
|
||||
|
||||
<form action="about:blank">
|
||||
<button id="form-2-button" onclick=@HandleClick>Click me</button>
|
||||
</form>
|
||||
|
||||
@if (didHandleEvent)
|
||||
{
|
||||
<p id="event-handled">Event was handled</p>
|
||||
}
|
||||
|
||||
@functions {
|
||||
bool didHandleEvent;
|
||||
|
||||
async Task HandleClick()
|
||||
{
|
||||
await Task.Delay(250); // To give time for default action if it's going to occur
|
||||
didHandleEvent = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
<option value="BasicTestApp.AfterRenderInteropComponent">After-render interop component</option>
|
||||
<option value="BasicTestApp.EventCasesComponent">Event cases</option>
|
||||
<option value="BasicTestApp.EventBubblingComponent">Event bubbling</option>
|
||||
<option value="BasicTestApp.EventPreventDefaultComponent">Event preventDefault</option>
|
||||
<option value="BasicTestApp.RouterTest.TestRouter">Router</option>
|
||||
</select>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue