sercrod

@keydown

Summary

@keydown attaches a handler to the native keydown event on an element. The expression on @keydown is evaluated every time a key is pressed while the element has focus (and may fire repeatedly if the key is held, depending on the browser and operating system).

Typical uses:

@keydown is part of Sercrod’s event handler family (such as @click, @input, @change, @focus, @blur) and uses the same evaluation and modifier rules as other @event directives.

Basic example

A simple handler that reacts to Enter and Escape:

<serc-rod id="app" data='{
  "log": [],
  "value": ""
}'>
  <input type="text"
         :value="value"
         @keydown="
           if($event.key === 'Enter'){
             log.push('submit:' + value);
           } else if($event.key === 'Escape'){
             value = '';
             log.push('clear');
           }
         ">

  <ul>
    <li *for="msg of log" *textContent="msg"></li>
  </ul>
</serc-rod>

Behavior:

Behavior

Core rules:

Event modifiers

@keydown supports the same modifier suffixes as other @event directives. Modifiers are appended to the attribute name, separated by dots:

Examples:

<input @keydown.prevent="handleKey($event)">
<input @keydown.stop="handleKey($event)">
<input @keydown.once="registerShortcut($event)">
<input @keydown.noupdate="handleKeyWithoutRerender($event)">

Rules specific to @keydown:

Evaluation timing

@keydown fits into Sercrod’s event and render pipeline as follows:

  1. Structural directives (*if, *for, *each, *switch, *include, etc.) first decide whether the element exists and in what form.

  2. Sercrod processes attributes on the kept element:

    • Colon bindings like :value, :class, :style, etc.
    • Event bindings such as @keydown, @input, @click.
  3. For @keydown, Sercrod extracts:

    • The event name "keydown" from the attribute name (after removing the configured prefix).
    • Any modifiers from the rest of the attribute name.
    • The expression string from the attribute value.
  4. Sercrod registers a real DOM event listener keydown on the element, using capture, passive, and once as requested.

  5. When the browser fires keydown:

    • Sercrod builds an evaluation scope that proxies the current data scope and injects $event / $e and el / $el.
    • Sercrod runs the expression through its event evaluator.
    • Sercrod then decides whether and how to re render based on the event name, modifiers, and configuration.

@keydown executes synchronously as part of the native event dispatch, so any side effects (such as updating data) happen immediately before any subsequent re renders.

Execution model and updates

Internally, after evaluating the handler expression, Sercrod chooses the update strategy:

This means @keydown is powerful but potentially expensive if many key events fire in quick succession and each triggers a full update. Use .noupdate or events.non_mutating if you need tight keyboard handling without frequent re renders.

Use with focusable controls and forms

@keydown is often paired with inputs and textareas:

With forms:

If you want to globally prevent Enter from submitting a form, consider using *prevent-default with the "enter" mode instead of repeating @keydown.prevent handlers on every control.

Use with conditionals and loops

@keydown composes cleanly with structural directives:

Each iteration gets its own @keydown handler, bound to that iteration’s item in scope.

Sercrod-specific restrictions

For @keydown itself, Sercrod does not impose special structural restrictions beyond the general event rules:

The main Sercrod specific consideration is update behavior:

Best practices

Additional examples

Arrow key navigation in a list:

<serc-rod id="app" data='{
  "items": ["Alpha", "Beta", "Gamma"],
  "index": 0
}'>
  <ul tabindex="0"
      @keydown="
        if($event.key === 'ArrowUp'){
          if(index > 0) index -= 1;
        } else if($event.key === 'ArrowDown'){
          if(index < items.length - 1) index += 1;
        }
      ">
    <li *for="(i, item) of items"
        :class="i === index ? 'is-active' : ''">
      {{%item%}}
    </li>
  </ul>
</serc-rod>

Closing a dialog with Escape:

<serc-rod id="dialogHost" data='{
  "open": true
}'>
  <div *if="open"
       class="dialog"
       tabindex="0"
       @keydown="
         if($event.key === 'Escape'){
           open = false;
         }
       ">
    <p>Press Escape to close.</p>
  </div>
</serc-rod>

Notes