Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Download Microsoft EdgeMore info about Internet Explorer and Microsoft Edge
Table of contentsExit editor mode

ASP.NET Core Blazor event handling

Feedback

In this article

Note

This isn't the latest version of this article. For the current release, see the.NET 10 version of this article.

Warning

This version of ASP.NET Core is no longer supported. For more information, see the.NET and .NET Core Support Policy. For the current release, see the.NET 9 version of this article.

This article explains Blazor's event handling features, including event argument types, event callbacks, and managing default browser events.

Delegate event handlers

Specify delegate event handlers in Razor component markup with@on{DOM EVENT}="{DELEGATE}" Razor syntax:

  • The{DOM EVENT} placeholder is aDOM event (for example,click).
  • The{DELEGATE} placeholder is the C# delegate event handler.

For event handling:

  • Delegate event handlers in Blazor Web Apps are only called in components that adopt an interactive render mode. The examples throughout this article assume that the app adopts an interactive render mode globally in the app's root component, typically theApp component. For more information, seeASP.NET Core Blazor render modes.
  • Asynchronous delegate event handlers that return aTask (async Task) are supported by Blazor and adopted by Blazor Web App and Blazor WebAssembly documentation examples.
  • Delegate event handlers automatically trigger a UI render, so there's no need to manually callStateHasChanged.
  • Exceptions are logged.
  • Asynchronous delegate event handlers that return aTask (async Task) are supported by Blazor and adopted by Blazor Server and Blazor WebAssembly documentation examples.
  • Delegate event handlers automatically trigger a UI render, so there's no need to manually callStateHasChanged.
  • Exceptions are logged.

Important

The Blazor framework doesn't trackvoid-returning asynchronous methods (async). As a result, the entire process fails when an exception isn't caught ifvoid is returned. Always return aTask/ValueTask from asynchronous methods.

The following code:

  • Calls theUpdateHeading method when the button is selected in the UI.
  • Calls theCheckChanged method when the checkbox is changed in the UI.

EventHandler1.razor:

@page "/event-handler-1"<PageTitle>Event Handler 1</PageTitle><h1>Event Handler Example 1</h1><h2>@headingValue</h2><p>    <button @onclick="UpdateHeading">        Update heading    </button></p><p>    <label>        <input type="checkbox" @onchange="CheckChanged" />        @checkedMessage    </label></p>@code {    private string headingValue = "Initial heading";    private string checkedMessage = "Not changed yet";    private void UpdateHeading() => headingValue = $"New heading ({DateTime.Now})";    private void CheckChanged() => checkedMessage = $"Last change {DateTime.Now}";}

EventHandler1.razor:

@page "/event-handler-1"<PageTitle>Event Handler 1</PageTitle><h1>Event Handler Example 1</h1><h2>@headingValue</h2><p>    <button @onclick="UpdateHeading">        Update heading    </button></p><p>    <label>        <input type="checkbox" @onchange="CheckChanged" />        @checkedMessage    </label></p>@code {    private string headingValue = "Initial heading";    private string checkedMessage = "Not changed yet";    private void UpdateHeading() => headingValue = $"New heading ({DateTime.Now})";    private void CheckChanged() => checkedMessage = $"Last change {DateTime.Now}";}

EventHandlerExample1.razor:

@page "/event-handler-1"<h1>@headingValue</h1><p>    <button @onclick="UpdateHeading">        Update heading    </button></p><p>    <label>        <input type="checkbox" @onchange="CheckChanged" />        @checkedMessage    </label></p>@code {    private string headingValue = "Initial heading";    private string checkedMessage = "Not changed yet";    private void UpdateHeading()    {        headingValue = $"New heading ({DateTime.Now})";    }    private void CheckChanged()    {        checkedMessage = $"Last changed at {DateTime.Now}";    }}

EventHandlerExample1.razor:

@page "/event-handler-1"<h1>@headingValue</h1><p>    <button @onclick="UpdateHeading">        Update heading    </button></p><p>    <label>        <input type="checkbox" @onchange="CheckChanged" />        @checkedMessage    </label></p>@code {    private string headingValue = "Initial heading";    private string checkedMessage = "Not changed yet";    private void UpdateHeading()    {        headingValue = $"New heading ({DateTime.Now})";    }    private void CheckChanged()    {        checkedMessage = $"Last changed at {DateTime.Now}";    }}

EventHandlerExample1.razor:

@page "/event-handler-1"<h1>@headingValue</h1><p>    <button @onclick="UpdateHeading">        Update heading    </button></p><p>    <label>        <input type="checkbox" @onchange="CheckChanged" />        @checkedMessage    </label></p>@code {    private string headingValue = "Initial heading";    private string checkedMessage = "Not changed yet";    private void UpdateHeading()    {        headingValue = $"New heading ({DateTime.Now})";    }    private void CheckChanged()    {        checkedMessage = $"Last changed at {DateTime.Now}";    }}

EventHandlerExample1.razor:

@page "/event-handler-1"<h1>@headingValue</h1><p>    <button @onclick="UpdateHeading">        Update heading    </button></p><p>    <label>        <input type="checkbox" @onchange="CheckChanged" />        @checkedMessage    </label></p>@code {    private string headingValue = "Initial heading";    private string checkedMessage = "Not changed yet";    private void UpdateHeading()    {        headingValue = $"New heading ({DateTime.Now})";    }    private void CheckChanged()    {        checkedMessage = $"Last changed at {DateTime.Now}";    }}

In the following example,UpdateHeading:

  • Is called asynchronously when the button is selected.
  • Waits two seconds before updating the heading.

EventHandler2.razor:

@page "/event-handler-2"<PageTitle>Event Handler 2</PageTitle><h1>Event Handler Example 2</h1><h2>@headingValue</h2><p>    <button @onclick="UpdateHeading">        Update heading    </button></p>@code {    private string headingValue = "Initial heading";    private async Task UpdateHeading()    {        await Task.Delay(2000);        headingValue = $"New heading ({DateTime.Now})";    }}

EventHandler2.razor:

@page "/event-handler-2"<PageTitle>Event Handler 2</PageTitle><h1>Event Handler Example 2</h1><h2>@headingValue</h2><p>    <button @onclick="UpdateHeading">        Update heading    </button></p>@code {    private string headingValue = "Initial heading";    private async Task UpdateHeading()    {        await Task.Delay(2000);        headingValue = $"New heading ({DateTime.Now})";    }}

EventHandlerExample2.razor:

@page "/event-handler-2"<h1>@headingValue</h1><p>    <button @onclick="UpdateHeading">        Update heading    </button></p>@code {    private string headingValue = "Initial heading";    private async Task UpdateHeading()    {        await Task.Delay(2000);        headingValue = $"New heading ({DateTime.Now})";    }}

EventHandlerExample2.razor:

@page "/event-handler-2"<h1>@headingValue</h1><p>    <button @onclick="UpdateHeading">        Update heading    </button></p>@code {    private string headingValue = "Initial heading";    private async Task UpdateHeading()    {        await Task.Delay(2000);        headingValue = $"New heading ({DateTime.Now})";    }}

EventHandlerExample2.razor:

@page "/event-handler-2"<h1>@headingValue</h1><p>    <button @onclick="UpdateHeading">        Update heading    </button></p>@code {    private string headingValue = "Initial heading";    private async Task UpdateHeading()    {        await Task.Delay(2000);        headingValue = $"New heading ({DateTime.Now})";    }}

EventHandlerExample2.razor:

@page "/event-handler-2"<h1>@headingValue</h1><p>    <button @onclick="UpdateHeading">        Update heading    </button></p>@code {    private string headingValue = "Initial heading";    private async Task UpdateHeading()    {        await Task.Delay(2000);        headingValue = $"New heading ({DateTime.Now})";    }}

Built-in event arguments

For events that support an event argument type, specifying an event parameter in the event method definition is only necessary if the event type is used in the method. In the following example,MouseEventArgs is used in theReportPointerLocation method to set message text that reports the mouse coordinates when the user selects a button in the UI.

EventHandler3.razor:

@page "/event-handler-3"<PageTitle>Event Handler 3</PageTitle><h1>Event Handler Example 3</h1>@for (var i = 0; i < 4; i++){    <p>        <button @onclick="ReportPointerLocation">            Where's my mouse pointer for this button?        </button>    </p>}<p>@mousePointerMessage</p>@code {    private string? mousePointerMessage;    private void ReportPointerLocation(MouseEventArgs e) =>         mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";}

EventHandler3.razor:

@page "/event-handler-3"<PageTitle>Event Handler 3</PageTitle><h1>Event Handler Example 3</h1>@for (var i = 0; i < 4; i++){    <p>        <button @onclick="ReportPointerLocation">            Where's my mouse pointer for this button?        </button>    </p>}<p>@mousePointerMessage</p>@code {    private string? mousePointerMessage;    private void ReportPointerLocation(MouseEventArgs e) =>         mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";}

EventHandlerExample3.razor:

@page "/event-handler-example-3"@for (var i = 0; i < 4; i++){    <p>        <button @onclick="ReportPointerLocation">            Where's my mouse pointer for this button?        </button>    </p>}<p>@mousePointerMessage</p>@code {    private string? mousePointerMessage;    private void ReportPointerLocation(MouseEventArgs e)    {        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";    }}

EventHandlerExample3.razor:

@page "/event-handler-example-3"@for (var i = 0; i < 4; i++){    <p>        <button @onclick="ReportPointerLocation">            Where's my mouse pointer for this button?        </button>    </p>}<p>@mousePointerMessage</p>@code {    private string? mousePointerMessage;    private void ReportPointerLocation(MouseEventArgs e)    {        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";    }}

EventHandlerExample3.razor:

@page "/event-handler-example-3"@for (var i = 0; i < 4; i++){    <p>        <button @onclick="ReportPointerLocation">            Where's my mouse pointer for this button?        </button>    </p>}<p>@mousePointerMessage</p>@code {    private string mousePointerMessage;    private void ReportPointerLocation(MouseEventArgs e)    {        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";    }}

EventHandlerExample3.razor:

@page "/event-handler-example-3"@for (var i = 0; i < 4; i++){    <p>        <button @onclick="ReportPointerLocation">            Where's my mouse pointer for this button?        </button>    </p>}<p>@mousePointerMessage</p>@code {    private string mousePointerMessage;    private void ReportPointerLocation(MouseEventArgs e)    {        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";    }}

SupportedEventArgs are shown in the following table.

EventClassDOM notes
ClipboardClipboardEventArgs
DragDragEventArgsDataTransfer andDataTransferItem hold dragged item data.

Implement drag and drop in Blazor apps usingJS interop withHTML Drag and Drop API.
ErrorErrorEventArgs
EventEventArgsEventHandlers holds attributes to configure the mappings between event names and event argument types.
FocusFocusEventArgsDoesn't include support forrelatedTarget.
InputChangeEventArgs
KeyboardKeyboardEventArgs
MouseMouseEventArgs
Mouse pointerPointerEventArgs
Mouse wheelWheelEventArgs
ProgressProgressEventArgs
TouchTouchEventArgsTouchPoint represents a single contact point on a touch-sensitive device.

For more information, see the following resources:

Custom event arguments

Blazor supports custom event arguments, which enable you to pass arbitrary data to .NET event handlers with custom events.

General configuration

Custom events with custom event arguments are generally enabled with the following steps.

In JavaScript, define a function for building the custom event argument object from the source event:

function eventArgsCreator(event) {   return {    customProperty1: 'any value for property 1',    customProperty2: event.srcElement.id  };}

Theevent parameter is aDOM Event.

Register the custom event with the preceding handler in aJavaScript initializer. Provide the appropriate browser event name tobrowserEventName, which for the example shown in this section isclick for a button selection in the UI.

wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js (the{PACKAGE ID/ASSEMBLY NAME} placeholder is the package ID or assembly name of the app):

For a Blazor Web App:

export function afterWebStarted(blazor) {  blazor.registerCustomEventType('customevent', {    browserEventName: 'click',    createEventArgs: eventArgsCreator  });}

For a Blazor Server or Blazor WebAssembly app:

export function afterStarted(blazor) {  blazor.registerCustomEventType('customevent', {    browserEventName: 'click',    createEventArgs: eventArgsCreator  });}

The call toregisterCustomEventType is performed in a script only once per event.

For the call toregisterCustomEventType, use theblazor parameter (lowercaseb) provided by the Blazor start event. Although the registration is valid when using theBlazor object (uppercaseB), the preferred approach is to use the parameter.

The custom event name,customevent in the preceding example, must not match a reserved Blazor event name. The reserved names can be found in theBlazor framework reference source (see the calls to theregisterBuiltInEventType function).

Note

Documentation links to .NET reference source usually load the repository's default branch, which represents the current development for the next release of .NET. To select a tag for a specific release, use theSwitch branches or tags dropdown list. For more information, seeHow to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205).

Define a class for the event arguments:

namespace BlazorSample.CustomEvents;public class CustomEventArgs : EventArgs{    public string? CustomProperty1 {get; set;}    public string? CustomProperty2 {get; set;}}

Wire up the custom event with the event arguments by adding an[EventHandler] attribute annotation for the custom event:

  • In order for the compiler to find the[EventHandler] class, it must be placed into a C# class file (.cs), making it a normal top-level class.
  • Mark the classpublic.
  • The class doesn't require members.
  • The classmust be called "EventHandlers" in order to be found by the Razor compiler.
  • Place the class under a namespace specific to your app.
  • Import the namespace into the Razor component (.razor) where the event is used.
using Microsoft.AspNetCore.Components;namespace BlazorSample.CustomEvents;[EventHandler("oncustomevent", typeof(CustomEventArgs),    enableStopPropagation: true, enablePreventDefault: true)]public static class EventHandlers{}

Register the event handler on one or more HTML elements. Access the data that was passed in from JavaScript in the delegate handler method:

@using BlazorSample.CustomEvents<button @oncustomevent="HandleCustomEvent">Handle</button>@if (!string.IsNullOrEmpty(propVal1) && !string.IsNullOrEmpty(propVal2)){    <ul>        <li>propVal1: @propVal1</li>        <li>propVal2: @propVal2</li>    </ul>}@code{    private string? propVal1;    private string? propVal2;    private void HandleCustomEvent(CustomEventArgs eventArgs)    {        propVal1 = eventArgs.CustomProperty1;        propVal2 = eventArgs.CustomProperty2;    }}

If the@oncustomevent attribute isn't recognized byIntelliSense, make sure that the component or the_Imports.razor file contains an@using statement for the namespace containing theEventHandler class.

Whenever the custom event is fired on the DOM, the event handler is called with the data passed from the JavaScript.

If you're attempting to fire a custom event,bubbles must be enabled by setting its value totrue. Otherwise, the event doesn't reach the Blazor handler for processing into the C# custom[EventHandler] attribute class. For more information, seeMDN Web Docs: Event bubbling.

Custom clipboard paste event example

The following example receives a custom clipboard paste event that includes the time of the paste and the user's pasted text.

Declare a custom name (oncustompaste) for the event and a .NET class (CustomPasteEventArgs) to hold the event arguments for this event:

CustomEvents.cs:

using Microsoft.AspNetCore.Components;namespace BlazorSample.CustomEvents;[EventHandler("oncustompaste", typeof(CustomPasteEventArgs),     enableStopPropagation: true, enablePreventDefault: true)]public static class EventHandlers{}public class CustomPasteEventArgs : EventArgs{    public DateTime EventTimestamp { get; set; }    public string? PastedData { get; set; }}

Add JavaScript code to supply data for theEventArgs subclass with the preceding handler in aJavaScript initializer. The following example only handles pasting text, but you could use arbitrary JavaScript APIs to deal with users pasting other types of data, such as images.

wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js:

For a Blazor Web App:

export function afterWebStarted(blazor) {  blazor.registerCustomEventType('custompaste', {    browserEventName: 'paste',    createEventArgs: event => {      return {        eventTimestamp: new Date(),        pastedData: event.clipboardData.getData('text')      };    }  });}

For a Blazor Server or Blazor WebAssembly app:

export function afterStarted(blazor) {  blazor.registerCustomEventType('custompaste', {    browserEventName: 'paste',    createEventArgs: event => {      return {        eventTimestamp: new Date(),        pastedData: event.clipboardData.getData('text')      };    }  });}

In the preceding example, the{PACKAGE ID/ASSEMBLY NAME} placeholder of the file name represents the package ID or assembly name of the app.

Note

For the call toregisterCustomEventType, use theblazor parameter (lowercaseb) provided by the Blazor start event. Although the registration is valid when using theBlazor object (uppercaseB), the preferred approach is to use the parameter.

The preceding code tells the browser that when a nativepaste event occurs:

  • Raise acustompaste event.
  • Supply the event arguments data using the custom logic stated:

Event name conventions differ between .NET and #"on".

  • In JavaScript, event names don't have a prefix.
  • In a Razor component, attach the custom handler to an element.

    CustomPasteArguments.razor:

    @page "/custom-paste-arguments"@using BlazorSample.CustomEvents<label>    Try pasting into the following text box:    <input @oncustompaste="HandleCustomPaste" /></label><p>    @message</p>@code {    private string? message;    private void HandleCustomPaste(CustomPasteEventArgs eventArgs)    {        message = $"At {eventArgs.EventTimestamp.ToShortTimeString()}, " +            $"you pasted: {eventArgs.PastedData}";    }}

    Lambda expressions

    Lambda expressions are supported as the delegate event handler.

    EventHandler4.razor:

    @page "/event-handler-4"<PageTitle>Event Handler 4</PageTitle><h1>Event Handler Example 4</h1><h2>@heading</h2><p>    <button @onclick="@(e => heading = "New heading!!!")">        Update heading    </button></p>@code {    private string heading = "Initial heading";}

    EventHandler4.razor:

    @page "/event-handler-4"<PageTitle>Event Handler 4</PageTitle><h1>Event Handler Example 4</h1><h2>@heading</h2><p>    <button @onclick="@(e => heading = "New heading!!!")">        Update heading    </button></p>@code {    private string heading = "Initial heading";}

    EventHandlerExample4.razor:

    @page "/event-handler-example-4"<h1>@heading</h1><p>    <button @onclick="@(e => heading = "New heading!!!")">        Update heading    </button></p>@code {    private string heading = "Initial heading";}

    EventHandlerExample4.razor:

    @page "/event-handler-example-4"<h1>@heading</h1><p>    <button @onclick="@(e => heading = "New heading!!!")">        Update heading    </button></p>@code {    private string heading = "Initial heading";}

    EventHandlerExample4.razor:

    @page "/event-handler-example-4"<h1>@heading</h1><p>    <button @onclick="@(e => heading = "New heading!!!")">        Update heading    </button></p>@code {    private string heading = "Initial heading";}

    EventHandlerExample4.razor:

    @page "/event-handler-example-4"<h1>@heading</h1><p>    <button @onclick="@(e => heading = "New heading!!!")">        Update heading    </button></p>@code {    private string heading = "Initial heading";}

    It's often convenient to close over additional values using C# method parameters, such as when iterating over a set of elements. The following example creates three buttons, each of which callsUpdateHeading and passes the following data:

    • An event argument (MouseEventArgs) ine.
    • The button number inbuttonNumber.

    EventHandler5.razor:

    @page "/event-handler-5"<PageTitle>Event Handler 5</PageTitle><h1>Event Handler Example 5</h1><h2>@heading</h2>@for (var i = 1; i < 4; i++){    var buttonNumber = i;    <p>        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">            Button #@i        </button>    </p>}@code {    private string heading = "Select a button to learn its position";    private void UpdateHeading(MouseEventArgs e, int buttonNumber) =>         heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";}

    EventHandler5.razor:

    @page "/event-handler-5"<PageTitle>Event Handler 5</PageTitle><h1>Event Handler Example 5</h1><h2>@heading</h2>@for (var i = 1; i < 4; i++){    var buttonNumber = i;    <p>        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">            Button #@i        </button>    </p>}@code {    private string heading = "Select a button to learn its position";    private void UpdateHeading(MouseEventArgs e, int buttonNumber) =>         heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";}

    EventHandlerExample5.razor:

    @page "/event-handler-example-5"<h1>@heading</h1>@for (var i = 1; i < 4; i++){    var buttonNumber = i;    <p>        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">            Button #@i        </button>    </p>}@code {    private string heading = "Select a button to learn its position";    private void UpdateHeading(MouseEventArgs e, int buttonNumber)    {        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";    }}

    EventHandlerExample5.razor:

    @page "/event-handler-example-5"<h1>@heading</h1>@for (var i = 1; i < 4; i++){    var buttonNumber = i;    <p>        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">            Button #@i        </button>    </p>}@code {    private string heading = "Select a button to learn its position";    private void UpdateHeading(MouseEventArgs e, int buttonNumber)    {        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";    }}

    EventHandlerExample5.razor:

    @page "/event-handler-example-5"<h1>@heading</h1>@for (var i = 1; i < 4; i++){    var buttonNumber = i;    <p>        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">            Button #@i        </button>    </p>}@code {    private string heading = "Select a button to learn its position";    private void UpdateHeading(MouseEventArgs e, int buttonNumber)    {        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";    }}

    EventHandlerExample5.razor:

    @page "/event-handler-example-5"<h1>@heading</h1>@for (var i = 1; i < 4; i++){    var buttonNumber = i;    <p>        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">            Button #@i        </button>    </p>}@code {    private string heading = "Select a button to learn its position";    private void UpdateHeading(MouseEventArgs e, int buttonNumber)    {        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";    }}

    Creating a large number of event delegates in a loop may cause poor rendering performance. For more information, seeASP.NET Core Blazor rendering performance best practices.

    Avoid using a loop variable directly in a lambda expression, such asi 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. Capture the variable's value in a local variable. In the preceding example:

    • The loop variablei is assigned tobuttonNumber.
    • buttonNumber is used in the lambda expression.

    Alternatively, use aforeach loop withEnumerable.Range, which doesn't suffer from the preceding problem:

    @foreach (var buttonNumber in Enumerable.Range(1, 3)){    <p>        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">            Button #@buttonNumber        </button>    </p>}

    EventCallback

    A common scenario with nested components is executing a method in a parent component when a child component event occurs. Anonclick event occurring in the child component is a common use case. To expose events across components, use anEventCallback. A parent component can assign a callback method to a child component'sEventCallback.

    The followingChild component demonstrates how a button'sonclick handler is set up to receive anEventCallback delegate from the sample'sParentComponent. TheEventCallback is typed withMouseEventArgs, which is appropriate for anonclick event from a peripheral device.

    Child.razor:

    <p>    <button @onclick="OnClickCallback">        Trigger a Parent component method    </button></p>@code {    [Parameter]    public string? Title { get; set; }    [Parameter]    public RenderFragment? ChildContent { get; set; }    [Parameter]    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }}
    <p>    <button @onclick="OnClickCallback">        Trigger a Parent component method    </button></p>@code {    [Parameter]    public string? Title { get; set; }    [Parameter]    public RenderFragment? ChildContent { get; set; }    [Parameter]    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }}
    <p>    <button @onclick="OnClickCallback">        Trigger a Parent component method    </button></p>@code {    [Parameter]    public string? Title { get; set; }    [Parameter]    public RenderFragment? ChildContent { get; set; }    [Parameter]    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }}
    <p>    <button @onclick="OnClickCallback">        Trigger a Parent component method    </button></p>@code {    [Parameter]    public string? Title { get; set; }    [Parameter]    public RenderFragment? ChildContent { get; set; }    [Parameter]    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }}
    <p>    <button @onclick="OnClickCallback">        Trigger a Parent component method    </button></p>@code {    [Parameter]    public string Title { get; set; }    [Parameter]    public RenderFragment ChildContent { get; set; }    [Parameter]    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }}
    <p>    <button @onclick="OnClickCallback">        Trigger a Parent component method    </button></p>@code {    [Parameter]    public string Title { get; set; }    [Parameter]    public RenderFragment ChildContent { get; set; }    [Parameter]    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }}

    The parent component sets the child'sEventCallback<TValue> (OnClickCallback) to itsShowMessage method.

    ParentChild.razor:

    @page "/parent-child"<PageTitle>Parent Child</PageTitle><h1>Parent Child Example</h1><Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">    Content of the child component is supplied by the parent component.</Child><p>@message</p>@code {    private string? message;    private void ShowMessage(MouseEventArgs e) =>         message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";}

    ParentChild.razor:

    @page "/parent-child"<PageTitle>Parent Child</PageTitle><h1>Parent Child Example</h1><Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">    Content of the child component is supplied by the parent component.</Child><p>@message</p>@code {    private string? message;    private void ShowMessage(MouseEventArgs e) =>         message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";}

    Parent.razor:

    @page "/parent"<h1>Parent-child example</h1><Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">    Content of the child component is supplied by the parent component.</Child><p>@message</p>@code {    private string? message;    private void ShowMessage(MouseEventArgs e)    {        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";    }}

    Parent.razor:

    @page "/parent"<h1>Parent-child example</h1><Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">    Content of the child component is supplied by the parent component.</Child><p>@message</p>@code {    private string? message;    private void ShowMessage(MouseEventArgs e)    {        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";    }}

    Parent.razor:

    @page "/parent"<h1>Parent-child example</h1><Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">    Content of the child component is supplied by the parent component.</Child><p>@message</p>@code {    private string message;    private void ShowMessage(MouseEventArgs e)    {        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";    }}

    Parent.razor:

    @page "/parent"<h1>Parent-child example</h1><Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">    Content of the child component is supplied by the parent component.</Child><p>@message</p>@code {    private string message;    private void ShowMessage(MouseEventArgs e)    {        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";    }}

    When the button is selected in theChildComponent:

    • TheParent component'sShowMessage method is called.message is updated and displayed in theParent component.
    • A call toStateHasChanged isn't required in the callback's method (ShowMessage).StateHasChanged is called automatically to rerender theParent component, just as child events trigger component rerendering in event handlers that execute within the child. For more information, seeASP.NET Core Razor component rendering.

    UseEventCallback andEventCallback<TValue> for event handling and binding component parameters.

    Prefer the strongly typedEventCallback<TValue> overEventCallback.EventCallback<TValue> provides enhanced error feedback when an inappropriate type is used, guiding users of the component towards correct implementation. Similar to other UI event handlers, specifying the event parameter is optional. UseEventCallback when there's no value passed to the callback.

    EventCallback andEventCallback<TValue> permit asynchronous delegates.EventCallback is weakly typed and allows passing any type argument inInvokeAsync(Object).EventCallback<TValue> is strongly typed and requires passing aT argument inInvokeAsync(T) that's assignable toTValue.

    Invoke anEventCallback orEventCallback<TValue> withInvokeAsync and await theTask:

    await OnClickCallback.InvokeAsync({ARGUMENT});

    In the preceding example, the{ARGUMENT} placeholder is an optional argument.

    The following parent-child example demonstrates the technique.

    Child2.razor:

    <h3>Child2 Component</h3><button @onclick="TriggerEvent">Click Me</button>@code {    [Parameter]    public EventCallback<string> OnClickCallback { get; set; }    private async Task TriggerEvent()    {        await OnClickCallback.InvokeAsync("Blaze It!");    }}

    ParentChild2.razor:

    @page "/parent-child-2"<PageTitle>Parent Child 2</PageTitle><h1>Parent Child 2 Example</h1><div>    <Child2 OnClickCallback="(value) => { message1 = value; }" />    @message1</div><div>    <Child2 OnClickCallback=        "async (value) => { await Task.Delay(2000); message2 = value; }" />     @message2</div>@code {    private string message1 = string.Empty;    private string message2 = string.Empty;}

    The second occurrence of theChild2 component demonstrates an asynchronous callback, and the newmessage2 value is assigned and rendered with a delay of two seconds.

    Prevent default actions

    Use the@on{DOM EVENT}:preventDefault directive attribute to prevent the default action for an event, where the{DOM EVENT} placeholder is aDOM 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@onkeydown:preventDefault directive attribute. When the focus is on the<input> element, the counter increments with the key sequenceShift++. The+ character isn't assigned to the<input> element's value. For more information onkeydown, seeMDN Web Docs: Document: keydown event.

    EventHandler6.razor:

    @page "/event-handler-6"<PageTitle>Event Handler 6</PageTitle><h1>Event Handler Example 6</h1><p>For this example, give the <code><input></code> focus.</p><p>    <label>        Count of '+' key presses:         <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />    </label></p>@code {    private int count = 0;    private void KeyHandler(KeyboardEventArgs e)    {        if (e.Key == "+")        {            count++;        }    }}

    EventHandler6.razor:

    @page "/event-handler-6"<PageTitle>Event Handler 6</PageTitle><h1>Event Handler Example 6</h1><p>For this example, give the <code><input></code> focus.</p><p>    <label>        Count of '+' key presses:         <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />    </label></p>@code {    private int count = 0;    private void KeyHandler(KeyboardEventArgs e)    {        if (e.Key == "+")        {            count++;        }    }}

    EventHandlerExample6.razor:

    @page "/event-handler-example-6"<p>    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault /></p>@code {    private int count = 0;    private void KeyHandler(KeyboardEventArgs e)    {        if (e.Key == "+")        {            count++;        }    }}

    EventHandlerExample6.razor:

    @page "/event-handler-example-6"<p>    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault /></p>@code {    private int count = 0;    private void KeyHandler(KeyboardEventArgs e)    {        if (e.Key == "+")        {            count++;        }    }}

    EventHandlerExample6.razor:

    @page "/event-handler-example-6"<p>    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault /></p>@code {    private int count = 0;    private void KeyHandler(KeyboardEventArgs e)    {        if (e.Key == "+")        {            count++;        }    }}

    EventHandlerExample6.razor:

    @page "/event-handler-example-6"<p>    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault /></p>@code {    private int count = 0;    private void KeyHandler(KeyboardEventArgs e)    {        if (e.Key == "+")        {            count++;        }    }}

    Specifying the@on{DOM EVENT}:preventDefault attribute without a value is equivalent to@on{DOM EVENT}:preventDefault="true".

    An expression is also a permitted value of the attribute. In the following example,shouldPreventDefault is abool field set to eithertrue orfalse:

    <input @onkeydown:preventDefault="shouldPreventDefault" />...@code {    private bool shouldPreventDefault = true;}

    Stop event propagation

    Use the@on{DOM EVENT}:stopPropagation directive attribute to stop event propagation within the Blazor scope.{DOM EVENT} is a placeholder for aDOM event.

    ThestopPropagation directive attribute's effect is limited to the Blazor scope and doesn't extend to the HTML DOM. Events must propagate to the HTML DOM root before Blazor can act upon them. For a mechanism to prevent HTML DOM event propagation, consider the following approach:

    In the following example, selecting the checkbox prevents click events from the second child<div> from propagating to the parent<div>. Since propagated click events normally fire theOnSelectParentDiv method, selecting the second child<div> results in the parent<div> message appearing unless the checkbox is selected.

    EventHandler7.razor:

    @page "/event-handler-7"<PageTitle>Event Handler 7</PageTitle><h1>Event Handler Example 7</h1><div>    <b>stopPropagation</b>: @stopPropagation</div><div>    <button @onclick="StopPropagation">        Stop Propagation (stopPropagation = true)    </button>    <button @onclick="EnablePropagation">        Enable Propagation (stopPropagation = false)    </button></div><div @onclick="OnSelectParentDiv">    <h3>Parent div</h3>    <div @onclick="OnSelectChildDiv">        Child div that never stops propagation to the parent div when         selected.    </div>    <div @onclick="OnSelectChildDiv"             @onclick:stopPropagation="stopPropagation">        Child div that stops propagation when selected if         <b>stopPropagation</b> is <b>true</b>.    </div></div><p>    @message</p>@code {    private bool stopPropagation = false;    private string? message;    private void StopPropagation() => stopPropagation = true;    private void EnablePropagation() => stopPropagation = false;    private void OnSelectParentDiv() =>         message = $"The parent div was selected. {DateTime.Now}";    private void OnSelectChildDiv() =>         message = $"The child div was selected. {DateTime.Now}";}

    EventHandler7.razor:

    @page "/event-handler-7"<PageTitle>Event Handler 7</PageTitle><h1>Event Handler Example 7</h1><div>    <b>stopPropagation</b>: @stopPropagation</div><div>    <button @onclick="StopPropagation">        Stop Propagation (stopPropagation = true)    </button>    <button @onclick="EnablePropagation">        Enable Propagation (stopPropagation = false)    </button></div><div @onclick="OnSelectParentDiv">    <h3>Parent div</h3>    <div @onclick="OnSelectChildDiv">        Child div that never stops propagation to the parent div when         selected.    </div>    <div @onclick="OnSelectChildDiv"             @onclick:stopPropagation="stopPropagation">        Child div that stops propagation when selected if         <b>stopPropagation</b> is <b>true</b>.    </div></div><p>    @message</p>@code {    private bool stopPropagation = false;    private string? message;    private void StopPropagation() => stopPropagation = true;    private void EnablePropagation() => stopPropagation = false;    private void OnSelectParentDiv() =>         message = $"The parent div was selected. {DateTime.Now}";    private void OnSelectChildDiv() =>         message = $"The child div was selected. {DateTime.Now}";}

    EventHandlerExample7.razor:

    @page "/event-handler-example-7"<div>    <b>stopPropagation</b>: @stopPropagation</div><div>    <button @onclick="StopPropagation">        Stop Propagation (stopPropagation = true)    </button>    <button @onclick="EnablePropagation">        Enable Propagation (stopPropagation = false)    </button></div><div @onclick="OnSelectParentDiv">    <h3>Parent div</h3>    <div @onclick="OnSelectChildDiv">        Child div that never stops propagation to the parent div when         selected.    </div>    <div @onclick="OnSelectChildDiv"             @onclick:stopPropagation="stopPropagation">        Child div that stops propagation when selected if         <b>stopPropagation</b> is <b>true</b>.    </div></div><p>    @message</p>@code {    private bool stopPropagation = false;    private string? message;    private void StopPropagation() => stopPropagation = true;    private void EnablePropagation() => stopPropagation = false;    private void OnSelectParentDiv() =>        message = $"The parent div was selected. {DateTime.Now}";    private void OnSelectChildDiv() =>        message = $"The child div was selected. {DateTime.Now}";}

    EventHandlerExample7.razor:

    @page "/event-handler-example-7"<div>    <b>stopPropagation</b>: @stopPropagation</div><div>    <button @onclick="StopPropagation">        Stop Propagation (stopPropagation = true)    </button>    <button @onclick="EnablePropagation">        Enable Propagation (stopPropagation = false)    </button></div><div @onclick="OnSelectParentDiv">    <h3>Parent div</h3>    <div @onclick="OnSelectChildDiv">        Child div that never stops propagation to the parent div when         selected.    </div>    <div @onclick="OnSelectChildDiv"             @onclick:stopPropagation="stopPropagation">        Child div that stops propagation when selected if         <b>stopPropagation</b> is <b>true</b>.    </div></div><p>    @message</p>@code {    private bool stopPropagation = false;    private string? message;    private void StopPropagation() => stopPropagation = true;    private void EnablePropagation() => stopPropagation = false;    private void OnSelectParentDiv() =>        message = $"The parent div was selected. {DateTime.Now}";    private void OnSelectChildDiv() =>        message = $"The child div was selected. {DateTime.Now}";}

    EventHandlerExample7.razor:

    @page "/event-handler-example-7"<div>    <b>stopPropagation</b>: @stopPropagation</div><div>    <button @onclick="StopPropagation">        Stop Propagation (stopPropagation = true)    </button>    <button @onclick="EnablePropagation">        Enable Propagation (stopPropagation = false)    </button></div><div @onclick="OnSelectParentDiv">    <h3>Parent div</h3>    <div @onclick="OnSelectChildDiv">        Child div that never stops propagation to the parent div when         selected.    </div>    <div @onclick="OnSelectChildDiv"             @onclick:stopPropagation="stopPropagation">        Child div that stops propagation when selected if         <b>stopPropagation</b> is <b>true</b>.    </div></div><p>    @message</p>@code {    private bool stopPropagation = false;    private string message;    private void StopPropagation() => stopPropagation = true;    private void EnablePropagation() => stopPropagation = false;    private void OnSelectParentDiv() =>        message = $"The parent div was selected. {DateTime.Now}";    private void OnSelectChildDiv() =>        message = $"The child div was selected. {DateTime.Now}";}

    EventHandlerExample7.razor:

    @page "/event-handler-example-7"<div>    <b>stopPropagation</b>: @stopPropagation</div><div>    <button @onclick="StopPropagation">        Stop Propagation (stopPropagation = true)    </button>    <button @onclick="EnablePropagation">        Enable Propagation (stopPropagation = false)    </button></div><div @onclick="OnSelectParentDiv">    <h3>Parent div</h3>    <div @onclick="OnSelectChildDiv">        Child div that never stops propagation to the parent div when         selected.    </div>    <div @onclick="OnSelectChildDiv"             @onclick:stopPropagation="stopPropagation">        Child div that stops propagation when selected if         <b>stopPropagation</b> is <b>true</b>.    </div></div><p>    @message</p>@code {    private bool stopPropagation = false;    private string message;    private void StopPropagation() => stopPropagation = true;    private void EnablePropagation() => stopPropagation = false;    private void OnSelectParentDiv() =>        message = $"The parent div was selected. {DateTime.Now}";    private void OnSelectChildDiv() =>        message = $"The child div was selected. {DateTime.Now}";}

    Focus an element

    CallFocusAsync on anelement reference to focus an element in code. In the following example, select the button to focus the<input> element.

    EventHandler8.razor:

    @page "/event-handler-8"<PageTitle>Event Handler 8</PageTitle><h1>Event Handler Example 8</h1><p>Select the button to give the <code><input></code> focus.</p><p>    <label>        Input:         <input @ref="exampleInput" />    </label>    </p><button @onclick="ChangeFocus">    Focus the Input Element</button>@code {    private ElementReference exampleInput;    private async Task ChangeFocus()    {        await exampleInput.FocusAsync();    }}

    EventHandler8.razor:

    @page "/event-handler-8"<PageTitle>Event Handler 8</PageTitle><h1>Event Handler Example 8</h1><p>Select the button to give the <code><input></code> focus.</p><p>    <label>        Input:         <input @ref="exampleInput" />    </label>    </p><button @onclick="ChangeFocus">    Focus the Input Element</button>@code {    private ElementReference exampleInput;    private async Task ChangeFocus()    {        await exampleInput.FocusAsync();    }}

    EventHandlerExample8.razor:

    @page "/event-handler-example-8"<p>    <input @ref="exampleInput" /></p><button @onclick="ChangeFocus">    Focus the Input Element</button>@code {    private ElementReference exampleInput;    private async Task ChangeFocus()    {        await exampleInput.FocusAsync();    }}

    EventHandlerExample8.razor:

    @page "/event-handler-example-8"<p>    <input @ref="exampleInput" /></p><button @onclick="ChangeFocus">    Focus the Input Element</button>@code {    private ElementReference exampleInput;    private async Task ChangeFocus()    {        await exampleInput.FocusAsync();    }}
    Collaborate with us on GitHub
    The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, seeour contributor guide.

    Feedback

    Was this page helpful?

    YesNoNo

    Need help with this topic?

    Want to try using Ask Learn to clarify or guide you through this topic?

    Suggest a fix?

    • Last updated on

    In this article

    Was this page helpful?

    YesNo
    NoNeed help with this topic?

    Want to try using Ask Learn to clarify or guide you through this topic?

    Suggest a fix?