16 KiB
title | author | description | monikerRange | ms.author | ms.custom | ms.date | no-loc | uid | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ASP.NET Core Blazor event handling | guardrex | Learn about Blazor's event handling features, including event argument types, event callbacks, and managing default browser events. | >= aspnetcore-3.1 | riande | mvc | 09/17/2020 |
|
blazor/components/event-handling |
ASP.NET Core Blazor event handling
By Luke Latham and Daniel Roth
Razor components provide event handling features. For an HTML element attribute named @on{EVENT}
(for example, @onclick
) with a delegate-typed value, a Razor component treats the attribute's value as an event handler.
The following code calls the UpdateHeading
method when the button is selected in the UI:
<button class="btn btn-primary" @onclick="UpdateHeading">
Update heading
</button>
@code {
private void UpdateHeading(MouseEventArgs e)
{
...
}
}
The following code calls the CheckChanged
method when the check box is changed in the UI:
<input type="checkbox" class="form-check-input" @onchange="CheckChanged" />
@code {
private void CheckChanged()
{
...
}
}
Event handlers can also be asynchronous and return a xref:System.Threading.Tasks.Task. There's no need to manually call StateHasChanged. Exceptions are logged when they occur.
In the following example, UpdateHeading
is called asynchronously when the button is selected:
<button class="btn btn-primary" @onclick="UpdateHeading">
Update heading
</button>
@code {
private async Task UpdateHeading(MouseEventArgs e)
{
...
}
}
Event argument types
For some events, event argument types are permitted. Specifying an event parameter in an event method definition is optional and only necessary if the event type is used in the method. In the following example, the MouseEventArgs
event argument is used in the ShowMessage
method to set message text:
private void ShowMessage(MouseEventArgs e)
{
messageText = $"The mouse is at coordinates: {e.ScreenX}:{e.ScreenY}";
}
Supported xref:System.EventArgs are shown in the following table.
::: moniker range=">= aspnetcore-5.0"
Event | Class | DOM events and notes |
---|---|---|
Clipboard | xref:Microsoft.AspNetCore.Components.Web.ClipboardEventArgs | oncut , oncopy , onpaste |
Drag | xref:Microsoft.AspNetCore.Components.Web.DragEventArgs | ondrag , ondragstart , ondragenter , ondragleave , ondragover , ondrop , ondragend xref:Microsoft.AspNetCore.Components.Web.DataTransfer and xref:Microsoft.AspNetCore.Components.Web.DataTransferItem hold dragged item data. Implement drag and drop in Blazor apps using JS interop with HTML Drag and Drop API. |
Error | xref:Microsoft.AspNetCore.Components.Web.ErrorEventArgs | onerror |
Event | xref:System.EventArgs | Generalonactivate , onbeforeactivate , onbeforedeactivate , ondeactivate , onfullscreenchange , onfullscreenerror , onloadeddata , onloadedmetadata , onpointerlockchange , onpointerlockerror , onreadystatechange , onscroll Clipboard onbeforecut , onbeforecopy , onbeforepaste Input oninvalid , onreset , onselect , onselectionchange , onselectstart , onsubmit Media oncanplay , oncanplaythrough , oncuechange , ondurationchange , onemptied , onended , onpause , onplay , onplaying , onratechange , onseeked , onseeking , onstalled , onstop , onsuspend , ontimeupdate , ontoggle , onvolumechange , onwaiting xref:Microsoft.AspNetCore.Components.Web.EventHandlers holds attributes to configure the mappings between event names and event argument types. |
Focus | xref:Microsoft.AspNetCore.Components.Web.FocusEventArgs | onfocus , onblur , onfocusin , onfocusout Doesn't include support for relatedTarget . |
Input | xref:Microsoft.AspNetCore.Components.ChangeEventArgs | onchange , oninput |
Keyboard | xref:Microsoft.AspNetCore.Components.Web.KeyboardEventArgs | onkeydown , onkeypress , onkeyup |
Mouse | xref:Microsoft.AspNetCore.Components.Web.MouseEventArgs | onclick , oncontextmenu , ondblclick , onmousedown , onmouseup , onmouseover , onmousemove , onmouseout |
Mouse pointer | xref:Microsoft.AspNetCore.Components.Web.PointerEventArgs | onpointerdown , onpointerup , onpointercancel , onpointermove , onpointerover , onpointerout , onpointerenter , onpointerleave , ongotpointercapture , onlostpointercapture |
Mouse wheel | xref:Microsoft.AspNetCore.Components.Web.WheelEventArgs | onwheel , onmousewheel |
Progress | xref:Microsoft.AspNetCore.Components.Web.ProgressEventArgs | onabort , onload , onloadend , onloadstart , onprogress , ontimeout |
Touch | xref:Microsoft.AspNetCore.Components.Web.TouchEventArgs | ontouchstart , ontouchend , ontouchmove , ontouchenter , ontouchleave , ontouchcancel xref:Microsoft.AspNetCore.Components.Web.TouchPoint represents a single contact point on a touch-sensitive device. |
::: moniker-end
::: moniker range="< aspnetcore-5.0"
Event | Class | DOM events and notes |
---|---|---|
Clipboard | xref:Microsoft.AspNetCore.Components.Web.ClipboardEventArgs | oncut , oncopy , onpaste |
Drag | xref:Microsoft.AspNetCore.Components.Web.DragEventArgs | ondrag , ondragstart , ondragenter , ondragleave , ondragover , ondrop , ondragend xref:Microsoft.AspNetCore.Components.Web.DataTransfer and xref:Microsoft.AspNetCore.Components.Web.DataTransferItem hold dragged item data. Implement drag and drop in Blazor apps using JS interop with HTML Drag and Drop API. |
Error | xref:Microsoft.AspNetCore.Components.Web.ErrorEventArgs | onerror |
Event | xref:System.EventArgs | Generalonactivate , onbeforeactivate , onbeforedeactivate , ondeactivate , onfullscreenchange , onfullscreenerror , onloadeddata , onloadedmetadata , onpointerlockchange , onpointerlockerror , onreadystatechange , onscroll Clipboard onbeforecut , onbeforecopy , onbeforepaste Input oninvalid , onreset , onselect , onselectionchange , onselectstart , onsubmit Media oncanplay , oncanplaythrough , oncuechange , ondurationchange , onemptied , onended , onpause , onplay , onplaying , onratechange , onseeked , onseeking , onstalled , onstop , onsuspend , ontimeupdate , onvolumechange , onwaiting xref:Microsoft.AspNetCore.Components.Web.EventHandlers holds attributes to configure the mappings between event names and event argument types. |
Focus | xref:Microsoft.AspNetCore.Components.Web.FocusEventArgs | onfocus , onblur , onfocusin , onfocusout Doesn't include support for relatedTarget . |
Input | xref:Microsoft.AspNetCore.Components.ChangeEventArgs | onchange , oninput |
Keyboard | xref:Microsoft.AspNetCore.Components.Web.KeyboardEventArgs | onkeydown , onkeypress , onkeyup |
Mouse | xref:Microsoft.AspNetCore.Components.Web.MouseEventArgs | onclick , oncontextmenu , ondblclick , onmousedown , onmouseup , onmouseover , onmousemove , onmouseout |
Mouse pointer | xref:Microsoft.AspNetCore.Components.Web.PointerEventArgs | onpointerdown , onpointerup , onpointercancel , onpointermove , onpointerover , onpointerout , onpointerenter , onpointerleave , ongotpointercapture , onlostpointercapture |
Mouse wheel | xref:Microsoft.AspNetCore.Components.Web.WheelEventArgs | onwheel , onmousewheel |
Progress | xref:Microsoft.AspNetCore.Components.Web.ProgressEventArgs | onabort , onload , onloadend , onloadstart , onprogress , ontimeout |
Touch | xref:Microsoft.AspNetCore.Components.Web.TouchEventArgs | ontouchstart , ontouchend , ontouchmove , ontouchenter , ontouchleave , ontouchcancel xref:Microsoft.AspNetCore.Components.Web.TouchPoint represents a single contact point on a touch-sensitive device. |
::: moniker-end
For more information, see the following resources:
EventArgs
classes in the ASP.NET Core reference source (dotnet/aspnetcoremaster
branch). Themaster
branch represents API under development for the next ASP.NET Core release. For the current release, select the appropriate GitHub repository branch (for example,release/3.1
).- MDN web docs: GlobalEventHandlers: Includes information on which HTML elements support each DOM event.
Lambda expressions
Lambda expressions can also be used:
<button @onclick="@(e => Console.WriteLine("Hello, world!"))">Say hello</button>
It's often convenient to close over additional values, such as when iterating over a set of elements. The following example creates three buttons, each of which calls UpdateHeading
passing an event argument (xref:Microsoft.AspNetCore.Components.Web.MouseEventArgs) and its button number (buttonNumber
) when selected in the UI:
<h2>@message</h2>
@for (var i = 1; i < 4; i++)
{
var buttonNumber = i;
<button class="btn btn-primary"
@onclick="@(e => UpdateHeading(e, buttonNumber))">
Button #@i
</button>
}
@code {
private string message = "Select a button to learn its position.";
private void UpdateHeading(MouseEventArgs e, int buttonNumber)
{
message = $"You selected Button #{buttonNumber} at " +
$"mouse position: {e.ClientX} X {e.ClientY}.";
}
}
[!NOTE] Do not use a loop variable directly in a lambda expression, such as
i
in the precedingfor
loop example. Otherwise, the same variable is used by all lambda expressions, which results in use of the same value in all lambdas. Always capture the variable's value in a local variable and then use it. In the preceding example, the loop variablei
is assigned tobuttonNumber
.
EventCallback
A common scenario with nested components is the desire to run a parent component's method when a child component event occurs. An onclick
event occurring in the child component is a common use case. To expose events across components, use an xref:Microsoft.AspNetCore.Components.EventCallback. A parent component can assign a callback method to a child component's xref:Microsoft.AspNetCore.Components.EventCallback.
The ChildComponent
in the sample app (Components/ChildComponent.razor
) demonstrates how a button's onclick
handler is set up to receive an xref:Microsoft.AspNetCore.Components.EventCallback delegate from the sample's ParentComponent
. The xref:Microsoft.AspNetCore.Components.EventCallback is typed with MouseEventArgs
, which is appropriate for an onclick
event from a peripheral device:
The ParentComponent
sets the child's xref:Microsoft.AspNetCore.Components.EventCallback%601 (OnClickCallback
) to its ShowMessage
method.
Pages/ParentComponent.razor
:
@page "/ParentComponent"
<h1>Parent-child example</h1>
<ChildComponent Title="Panel Title from Parent"
OnClickCallback="@ShowMessage">
Content of the child component is supplied
by the parent component.
</ChildComponent>
<p><b>@messageText</b></p>
@code {
private string messageText;
private void ShowMessage(MouseEventArgs e)
{
messageText = $"Blaze a new trail with Blazor! ({e.ScreenX}, {e.ScreenY})";
}
}
When the button is selected in the ChildComponent
:
- The
ParentComponent
'sShowMessage
method is called.messageText
is updated and displayed in theParentComponent
. - A call to
StateHasChanged
isn't required in the callback's method (ShowMessage
). xref:Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged%2A is called automatically to rerender theParentComponent
, just as child events trigger component rerendering in event handlers that execute within the child.
xref:Microsoft.AspNetCore.Components.EventCallback and xref:Microsoft.AspNetCore.Components.EventCallback%601 permit asynchronous delegates. xref:Microsoft.AspNetCore.Components.EventCallback is weakly typed and allows passing any type argument in InvokeAsync(Object)
. xref:Microsoft.AspNetCore.Components.EventCallback%601 is strongly typed and requires passing a T
argument in InvokeAsync(T)
that's assignable to TValue
.
<ChildComponent
OnClickCallback="@(async () => { await Task.Yield(); messageText = "Blaze It!"; })" />
Invoke an xref:Microsoft.AspNetCore.Components.EventCallback or xref:Microsoft.AspNetCore.Components.EventCallback%601 with xref:Microsoft.AspNetCore.Components.EventCallback.InvokeAsync%2A and await the xref:System.Threading.Tasks.Task:
await OnClickCallback.InvokeAsync(arg);
Use xref:Microsoft.AspNetCore.Components.EventCallback and xref:Microsoft.AspNetCore.Components.EventCallback%601 for event handling and binding component parameters.
Prefer the strongly typed xref:Microsoft.AspNetCore.Components.EventCallback%601 over xref:Microsoft.AspNetCore.Components.EventCallback. xref:Microsoft.AspNetCore.Components.EventCallback%601 provides better error feedback to users of the component. Similar to other UI event handlers, specifying the event parameter is optional. Use xref:Microsoft.AspNetCore.Components.EventCallback when there's no value passed to the callback.
Prevent default actions
Use the @on{EVENT}:preventDefault
directive attribute to prevent the default action for an event.
When a key is selected on an input device and the element focus is on a text box, a browser normally displays the key's character in the text box. In the following example, the default behavior is prevented by specifying the @onkeypress:preventDefault
directive attribute. The counter increments, and the + key isn't captured into the <input>
element's value:
<input value="@count" @onkeypress="KeyHandler" @onkeypress:preventDefault />
@code {
private int count = 0;
private void KeyHandler(KeyboardEventArgs e)
{
if (e.Key == "+")
{
count++;
}
}
}
Specifying the @on{EVENT}:preventDefault
attribute without a value is equivalent to @on{EVENT}:preventDefault="true"
.
The value of the attribute can also be an expression. In the following example, shouldPreventDefault
is a bool
field set to either true
or false
:
<input @onkeypress:preventDefault="shouldPreventDefault" />
Stop event propagation
Use the @on{EVENT}:stopPropagation
directive attribute to stop event propagation.
In the following example, selecting the check box prevents click events from the second child <div>
from propagating to the parent <div>
:
<label>
<input @bind="stopPropagation" type="checkbox" />
Stop Propagation
</label>
<div @onclick="OnSelectParentDiv">
<h3>Parent div</h3>
<div @onclick="OnSelectChildDiv">
Child div that doesn't stop propagation when selected.
</div>
<div @onclick="OnSelectChildDiv" @onclick:stopPropagation="stopPropagation">
Child div that stops propagation when selected.
</div>
</div>
@code {
private bool stopPropagation = false;
private void OnSelectParentDiv() =>
Console.WriteLine($"The parent div was selected. {DateTime.Now}");
private void OnSelectChildDiv() =>
Console.WriteLine($"A child div was selected. {DateTime.Now}");
}