blazor-eventos-dom-onclick-keyboard

DOM Events in Blazor: Clicks, Keyboard, and Arguments

  • 4 min

A DOM event is a notification generated by the browser when the user or the page performs an action.

In Blazor we can respond to clicks, keys, or form changes with C# methods bound from Razor markup, without manually registering a listener with addEventListener.

Basic @onevent Syntax

The general rule in Blazor is very simple: any standard HTML DOM event has an equivalent Razor syntax that starts with @on followed by the event name.

  • onclick => @onclick
  • onchange => @onchange
  • oninput => @oninput
  • onkeydown => @onkeydown

To handle the event, we simply assign a C# method to that attribute.

<button class="btn btn-primary" @onclick="ProcesarClick">
    Click Here
</button>

<p>Message: @mensaje</p>

@code {
    private string mensaje = "Waiting...";

    private void ProcesarClick()
    {
        mensaje = "Button pressed at " + DateTime.Now.ToLongTimeString() + "!";
    }
}
Copied!

When the event finishes executing, Blazor automatically calls StateHasChanged(). This causes the component to re-render to reflect changes in the UI (like updating the mensaje variable).

Event Arguments

Often, simply knowing that “something happened” is not enough. We need details.

  • If it’s a click, where did the user click? Was the CTRL key pressed?
  • If it’s a key, which letter was pressed?

Blazor allows us to receive an argument object in our handler method. The type of this object depends on the event.

MouseEventArgs

For mouse events (@onclick, @onmousemove, etc.), the method can accept a MouseEventArgs parameter.

<div style="background-color: lightgray; height: 200px;"
     @onclick="MostrarCoordenadas">
    Click inside this box.
</div>

<p>@coordenadas</p>

@code {
    private string coordenadas;

    private void MostrarCoordenadas(MouseEventArgs e)
    {
        coordenadas = $"X: {e.ClientX}, Y: {e.ClientY}";

        if (e.CtrlKey)
        {
            coordenadas += " (With CTRL key pressed!)";
        }
    }
}
Copied!

KeyboardEventArgs

For keyboard events, we use KeyboardEventArgs. This is essential for creating keyboard shortcuts or interactive inputs.

<input type="text" @onkeydown="VerificarTecla" placeholder="Type something..." />

<p>@estado</p>

@code {
    private string estado;

    private void VerificarTecla(KeyboardEventArgs e)
    {
        if (e.Key == "Enter")
        {
            estado = "You pressed ENTER! Processing...";
        }
        else
        {
            estado = $"Key pressed: {e.Key} (Code: {e.Code})";
        }
    }
}
Copied!

In a text field, @onchange fires when the user confirms the change (usually when losing focus or pressing Enter), while @oninput responds to every change in value. For real-time search, @oninput is usually the right choice.

Passing Custom Arguments with Lambda Expressions

This is the most common scenario and where most people get stuck at first.

Suppose you have a list generated with @foreach and you want the “Delete” button to act on a specific item.

The standard event handler doesn’t work because we need to pass it the Id or the Item object. The solution is to use a Lambda Expression.

<h3>Task List</h3>

<ul>
    @foreach (var tarea in Tareas)
    {
        <li>
            @tarea.Nombre
            <button @onclick="() => BorrarTarea(tarea.Id)">
                🗑️ Delete
            </button>
        </li>
    }
</ul>

@code {
    private void BorrarTarea(int idTarea)
    {
        var tareaABorrar = Tareas.FirstOrDefault(t => t.Id == idTarea);
        if (tareaABorrar != null)
        {
            Tareas.Remove(tareaABorrar);
        }
    }

    // ... definition of Tareas list ...
}
Copied!

The syntax () => Metodo(parametro) creates a small anonymous function that Blazor will execute when the event occurs.

Event Modifiers: preventDefault and stopPropagation

Sometimes we need to control the native behavior of the browser.

  1. preventDefault: Prevents the default action. For example, preventing a form from submitting or preventing a key press in an input from typing a character.
  2. stopPropagation: Prevents the event from “bubbling up” to parent elements.

In Blazor, this is done using attribute directives.

<a href="https://google.com"
   @onclick="LogClick"
   @onclick:preventDefault="true">
   Disabled link
</a>

<div @onclick="ClickPadre">
    Parent
    <button @onclick="ClickHijo" @onclick:stopPropagation="true">
        Child (Does not trigger the parent event)
    </button>
</div>
Copied!

Asynchronous Events

Event handlers can return Task. If you are going to wait for a database or an API when a click happens, use async Task instead of async void.

private async Task CargarDatos()
{
    IsLoading = true;
    // Blazor detects this await and allows the UI to update to show "Loading..."
    await Task.Delay(2000);
    IsLoading = false;
}
Copied!

Blazor is smart enough to wait for the Task to finish and perform a final render.