preventDefault for form onsubmit handlers. Fixes #951

This commit is contained in:
Steve Sanderson 2018-07-23 11:02:50 -07:00
parent 79c60c91af
commit 4aaeac1e51
4 changed files with 66 additions and 2 deletions

View File

@ -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,

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

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