Radiant0.3.0

createEventListener

createEventListener subscribes to DOM events with delegation, window, or document targeting. It is the functional equivalent of the @onEvent decorator, designed for vanilla JS usage.

Listeners are automatically attached on connect and detached on disconnect. The returned cleanup function permanently removes the listener.

Usage

import { RadiantElement } from '@ecopages/radiant';
import { createEventListener } from '@ecopages/radiant/helpers/create-event-listener';
 
class ClickCounter extends RadiantElement {
	#count = 0;
 
	constructor() {
		super();
		createEventListener(this, { selector: 'button', type: 'click' }, () => {
			this.#count++;
			console.log(`Clicked ${this.#count} times`);
		});
	}
}
 
customElements.define('click-counter', ClickCounter);

Use it with authored light DOM:

<click-counter>
	<button type="button">Click me</button>
</click-counter>

Parameters

createEventListener(host, config, callback) accepts:

ParameterTypeRequiredDescription
hostRadiantElementYesThe host element for lifecycle binding.
configOnEventConfigYesEvent configuration (see below).
callback(event: Event) => voidYesThe event handler.

OnEventConfig — Target Selection (choose one)

FieldTypeDescription
selectorstringCSS selector for delegated matching.
refstringValue of data-ref for delegated matching.
windowtrueListen on the global window object.
documenttrueListen on the global document object.

OnEventConfig — Event Options

FieldTypeRequiredDescription
typestringYesEvent type (e.g., 'click', 'input', 'keydown').
optionsAddEventListenerOptionsNoStandard options like { passive: true, once: true }.

Return Value

Returns a () => void cleanup function. Calling it permanently removes the listener, even across reconnects.

const cleanup = createEventListener(host, { ref: 'btn', type: 'click' }, handler);
 
// Later: permanently stop listening
cleanup();

Delegated Events

When using selector or ref, the listener is delegated to the host element. Events bubble up from the target, and the handler fires only when event.target matches the selector.

Because delegation relies on bubbling, it does not work with events that do not bubble (e.g., focus, blur). Use their bubbling alternatives (focusin, focusout).

Window and Document Events

createEventListener(
	host,
	{ window: true, type: 'scroll', options: { passive: true } },
	() => console.log('scrolled'),
);
 
createEventListener(
	host,
	{ document: true, type: 'keydown' },
	(event) => {
		if ((event as KeyboardEvent).key === 'Escape') {
			console.log('escape pressed');
		}
	},
);

Learn More