Clone on Gitea
Introduction
Explained by ducks
FAQ
Getting Started
Components
Component Basics
Auto Initialization From DOM
Templates
Children and Parents
Roles
Strictness
Fields
What is a Field
Binding Fields to DOM
Reading and Writing Fields
Value Casting
Flags
Events
Overview
Event Handlers
DOM Events
Custom Events
Propagation and Flow
Advanced Event Control
Beyond Components
States
Overview
StateEngine
DisplayStateEngine
Field Matchers
Ordering and priority
Debugging
Advanced usage
Ajax
ComponentUI
VirtualForm
Unit Testing
Helpers
Overview
Cookies
Arrays

Events overview

Events are how Qite components communicate. If you write components, you mainly care about two things:

  1. Declaring handlers for events you want to react to.
  2. Publishing your own events for your parent component (or for yourself).

Qite treats DOM events and custom events as the same thing: they are both "published" and then "captured" using the same API. This keeps component code consistent: one mental model for "@click" and for "submit". Below is a small sketch of what event code looks like.

class MyComponent extends BaseComponent {
    constructor(tree_node) {
        super(tree_node);

        this.events.add([
            ["@click", "#close", (e)    => this.remove()          ],
            ["submit", ">form",  (data) => this.handleSubmit(data)]
            // ---^---------^--------------------------------------
            // event name   event source
        ]);
    }

    ...
    // Somewhere else inside component methods:
    this.events.publish("submit", { data: { ok: true } });
    ...
}

Do not memorize this. The point is simple: all events look the same. The next pages explain events.add(...) and event sources in detail.

Events are very useful when reacting to user input or child component signals. But if you over-use them, you may end up managing complex state transitions manually. As a rule of thumb: if you notice you are orchestrating UI state with chains of events, it may be time to use states instead. States are built on top of events and provide a more declarative way to manage UI logic.

The mental model

Every component has an events object and you use it to register handlers with events.add(...) and then you can also emit events with events.publish(...)

A component also has a parent, and parents automatically subscribe to their children. This means child events flow upward in a predictable way. So the flow is usually like this:

  1. A child publishes an event.
  2. The parent receives it and decides what to do.
  3. The parent may update fields, flags, state, UI, or publish another event upward.

This is the default style in Qite: parents orchestrate, children signal.

Two kinds of events

Qite has two event categories: DOM events(native browser events) and custom events(events you publish yourself). DOM events are written with an "@" prefix in event names, for example "@click". Custom events do not use "@", for example "submit" or "remove"

From a component author's point of view, the difference is simple:

  • DOM events carry the native browser event object.
  • Custom events carry whatever you pass as data

If you're designing a low-level component (like a button or a form field), you will mostly subscribe to DOM events such as "@click" or "@input". But when you're working on a higher-level component, you will usually subscribe to events published by child components. However there is no rule forcing you to choose one or the other category of events — you can freely combine DOM and custom events inside the same component.

What you can listen to

Handlers may be triggered by different kinds of events:

  • Custom events published by child components.
  • Native browser events for DOM-elements inside your component.
  • Events published by the component itself.

Regardless of where they originate, they are declared and handled in the same way. The difference lies only in what triggered them and what data they carry. The next pages explain how to declare sources precisely and how event data is passed to handlers.

Built-in component events

BaseComponent publishes several useful events automatically:

  • "field_change"— one or more fields changed, payload is the list of changed field names.
  • "flag_change"— one or more flags changed, payload is the list of changed flag names.
  • "remove"— component was removed from the DOM.
  • "move"— component was moved to a different parent.

These events are stable integration points. In practice, most component authors will subscribe to DOM or custom child events instead. The built-in ones are used heavily by state engines, which are covered later.