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 selectValuePropname = '_blazorSelectValue';
|
||||||
const sharedTemplateElemForParsing = document.createElement('template');
|
const sharedTemplateElemForParsing = document.createElement('template');
|
||||||
const sharedSvgElemForParsing = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
const sharedSvgElemForParsing = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
|
const preventDefaultEvents: { [eventType: string]: boolean } = { submit: true };
|
||||||
let raiseEventMethod: MethodHandle;
|
let raiseEventMethod: MethodHandle;
|
||||||
let renderComponentMethod: 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 = {
|
const eventDescriptor = {
|
||||||
browserRendererId,
|
browserRendererId,
|
||||||
componentId,
|
componentId,
|
||||||
|
|
@ -362,7 +367,7 @@ async function raiseEvent(event: Event, browserRendererId: number, componentId:
|
||||||
eventArgsType: eventArgs.type
|
eventArgsType: eventArgs.type
|
||||||
};
|
};
|
||||||
|
|
||||||
await DotNet.invokeMethodAsync(
|
return DotNet.invokeMethodAsync(
|
||||||
'Microsoft.AspNetCore.Blazor.Browser',
|
'Microsoft.AspNetCore.Blazor.Browser',
|
||||||
'DispatchEvent',
|
'DispatchEvent',
|
||||||
eventDescriptor,
|
eventDescriptor,
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure.ServerFixtures;
|
using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure.ServerFixtures;
|
||||||
using OpenQA.Selenium;
|
using OpenQA.Selenium;
|
||||||
using OpenQA.Selenium.Interactions;
|
using OpenQA.Selenium.Interactions;
|
||||||
|
using OpenQA.Selenium.Support.UI;
|
||||||
|
using System;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
|
@ -108,5 +110,22 @@ namespace Microsoft.AspNetCore.Blazor.E2ETest.Tests
|
||||||
actions.Perform();
|
actions.Perform();
|
||||||
WaitAssert.Equal("onmousedown,onmouseup,", () => output.Text);
|
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.AfterRenderInteropComponent">After-render interop component</option>
|
||||||
<option value="BasicTestApp.EventCasesComponent">Event cases</option>
|
<option value="BasicTestApp.EventCasesComponent">Event cases</option>
|
||||||
<option value="BasicTestApp.EventBubblingComponent">Event bubbling</option>
|
<option value="BasicTestApp.EventBubblingComponent">Event bubbling</option>
|
||||||
|
<option value="BasicTestApp.EventPreventDefaultComponent">Event preventDefault</option>
|
||||||
<option value="BasicTestApp.RouterTest.TestRouter">Router</option>
|
<option value="BasicTestApp.RouterTest.TestRouter">Router</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue