sercrod

@keyup

Summary

@keyup attaches a handler to the native keyup event on an element. The expression on @keyup is evaluated when the user releases a key while the element has focus. Typical uses include:

@keyup is part of the event handler family (such as @click, @input, @keydown) and follows the same generic event rules in Sercrod.

Basic example

Triggering search when the user presses Enter:

<serc-rod id="search-app" data='{
  "query": "",
  "results": [],
  "last_key": ""
}'>
  <input type="search"
         :value="query"
         @keyup="
           last_key = $event.key;
           if($event.key === 'Enter'){
             search(query);
           }
         ">

  <p *if="last_key">
    Last key: {{%last_key%}}
  </p>

  <ul>
    <li *for="item of results">{{%item%}}</li>
  </ul>
</serc-rod>

Behavior:

Behavior

Core rules:

Evaluation timing

@keyup participates in Sercrod’s normal rendering and event lifecycle:

There is no special debounce or delay attached to @keyup itself; it executes in the same turn as the native event.

Execution model

At a high level, the runtime behaves as follows for @keyup:

  1. During rendering, Sercrod finds an attribute whose name starts with the event prefix (by default "@") and whose event name portion is "keyup".

  2. It extracts:

    • the event name ev = "keyup",
    • the list of modifiers (for example "prevent", "stop", "once", "capture", "passive"),
    • the expression string from the attribute value, for example onKey($event).
  3. It constructs listener options from modifiers:

    • capture: mods.has("capture"),
    • passive: mods.has("passive"),
    • once: mods.has("once").
  4. It defines a handler handler(e) that:

    • Applies preventDefault if mods contains "prevent".

    • Applies stopPropagation if mods contains "stop".

    • Constructs an evaluation scope in which:

      • $event and $e refer to e,
      • el and $el refer to the element,
      • other names are resolved first against Sercrod data, then against the provided scope, and finally against window.
    • Calls this.eval_event(expr, scope, { el, $event: e }) to execute the expression.

    • Decides the update strategy and runs a suitable update method (see below).

    • If the "once" modifier was present, removes the handler from the element after the first call.

  5. Before attaching the handler, Sercrod ensures that there is at most one handler per event name on the element:

    • It keeps a private el._sercrod_handlers[ev].
    • If a previous handler exists for "keyup", it is removed before the new handler is attached.
  6. It attaches the handler using el.addEventListener("keyup", handler, options).

This mechanism is shared by all @event directives; @keyup is one instance of this generic path, with the event name "keyup".

Key data and $event

Inside a @keyup handler expression:

Update behavior for @keyup

@keyup is treated as an input-like event in Sercrod’s update strategy.

After the handler runs, the runtime computes:

For ev === "keyup":

This has two practical consequences:

The classification as input-like is built into the runtime and is independent of the default non_mutating configuration (which lists hover and pointer events, but not keyup).

Use with loops and conditionals

@keyup composes naturally with structural directives controlling the element itself:

Structural directives do not change the semantics of @keyup; they only decide whether the element (and its handler) exist in the rendered tree.

Use with form inputs and staged updates

@keyup is especially useful for form inputs and staged editing:

Sercrod-specific restrictions

For @keyup, the main Sercrod-specific points are:

There are no special combination restrictions unique to @keyup:

Best practices

Additional examples

Simple shortcut: submit on Enter, ignore other keys:

<form *post="'/api/search:result'">
  <input type="search"
         :value="query"
         @keyup="
           if($event.key === 'Enter'){
             $el.form.requestSubmit();
           }
         ">

  <button type="submit">Search</button>
</form>

Toggle a help overlay with a keyboard shortcut:

<serc-rod id="help-app" data='{
  "show_help": false
}'>
  <input type="text"
         :value="input"
         @keyup="
           if($event.key === 'F1'){
             show_help = !show_help;
           }
         ">

  <aside *if="show_help">
    Press F1 again to hide this help.
  </aside>
</serc-rod>

Implement a simple key logger for debugging:

<serc-rod id="logger" data='{
  "keys": []
}'>
  <input type="text"
         @keyup="
           keys.push($event.key);
           if(keys.length > 20) keys.shift();
         ">

  <p>Recent keys: {{%keys.join(' ')%}}</p>
</serc-rod>

Notes