sercrod

@click

Summary

@click attaches a handler to the native click event on an element. The expression on @click is evaluated every time the element is clicked.

Typical uses:

@click belongs to the general event handler family (such as @input, @change, @blur, @focus) and follows the same evaluation rules as other @event directives.

Basic example

A simple counter:

<serc-rod id="app" data='{
  "count": 0
}'>
  <button @click="count++">
    Clicked {{%count%}} times
  </button>
</serc-rod>

Behavior:

Accessing the event and element

When a click event fires, Sercrod evaluates the @click expression with a special event scope:

Example:

<serc-rod id="app" data='{
  "log": []
}'>
  <button @click="log.push({ x: $event.clientX, y: $event.clientY })">
    Log click position
  </button>
</serc-rod>

Assignments to $event, $e, $el, or el are not used by Sercrod internally; treat them as read only in event expressions.

Behavior

Core rules:

Evaluation timing and re-rendering

@click participates in the normal render and update cycle for a Sercrod host:

  1. Structural directives such as *if, *for, *each, *switch, and *include decide whether the element is present. If the element is removed by a structural directive, no handler is attached.

  2. During attribute processing, Sercrod recognises attributes starting with the configured event prefix (by default "@"). Each event attribute (such as @click) is converted into a listener with its expression and modifiers.

  3. When the native click fires:

    • Sercrod builds the merged event scope (data plus $event, $el, and global fallback).
    • Sercrod evaluates the expression.
    • If evaluation throws, Sercrod logs the error (when error.warn is enabled) but does not halt the framework.
  4. After the expression runs, Sercrod decides how to re-render:

    • It reads the events.non_mutating list from configuration.
    • It treats click as a mutating event by default (so it usually causes an update).
    • For clicks on form controls (inputs, textareas, selects, or contentEditable elements) Sercrod prefers a lightweight child update to preserve focus.
    • For other clicks, Sercrod triggers a full host update unless the modifiers override this (see .update and .noupdate).

You usually do not need to call any manual update function. Changing data in @click handlers is sufficient to trigger re-renders according to these rules.

@click is most natural on interactive elements:

Use with forms and submission

@click often appears on form buttons:

<serc-rod id="app" data='{
  "profile": { "name": "" },
  "saving": false
}'>
  <form method="post" :action="saveUrl">
    <input type="text" name="name" :value="profile.name">

    <button type="submit"
            @click.prevent="saving = true; submitProfile(profile)">
      Save
    </button>
  </form>
</serc-rod>

Typical patterns:

For clicks on form controls (inputs, textareas, selects) or on buttons that are treated as input controls, Sercrod performs a lightweight child update to keep focus stable while still reflecting data changes.

Modifiers

@click supports a set of event modifiers that are shared by all @event directives.

There are three kinds of modifiers:

Concretely:

Example:

<button @click.noupdate="log.push('clicked')">
  Log without re-render
</button>

Use with conditionals and loops

@click composes naturally with structural directives:

When structural directives replace or remove the element, Sercrod tears down and re-attaches @click listeners as needed, so you do not need to manage them manually.

Best practices

Additional examples

Toggle a menu:

<serc-rod id="menu" data='{
  "open": false
}'>
  <button @click="open = !open">
    {{% open ? 'Close menu' : 'Open menu' %}}
  </button>

  <nav *if="open">
    <!-- menu items -->
  </nav>
</serc-rod>

Call a shared method with the event:

<serc-rod id="app" data='{
  "log": []
}'>
  <button @click="logClick($event, 'primary')">
    Primary
  </button>
  <button @click="logClick($event, 'secondary')">
    Secondary
  </button>
</serc-rod>

Attach @click to a container with nested controls:

<div class="card" @click="select(item)">
  <h2 *print="item.title"></h2>
  <p *print="item.summary"></p>
  <button type="button" @click.stop="openDetails(item)">
    Details
  </button>
</div>

In this example:

Notes