A tiny TypeScript library for DOM event delegation with powerful action dispatching to web components.
- 🚀 Lightweight - minimal footprint, no dependencies
- 🎯 Event Delegation - efficient event handling using event delegation pattern
- 🔧 Web Components - seamless integration with custom web components
- 🏃 Performance - sync/async execution modes
- 🛡️ TypeScript - full TypeScript support with type safety
- 🔌 Interceptors - custom event handling logic
npm install @alexander.k/event-delegatorimport { eventDelegator } from '@alexander.k/event-delegator'
// Initialize event delegation for click events
eventDelegator({
events: ['click']
})eventDelegator({
events: ['click', 'input', 'change'], // Events to listen for
capture: true, // Use capture phase
attributePrefix: 'data-ed-', // Custom attribute prefix
interceptors: [ // Custom interceptors
({ target, method, params, element }) => {
// Log all actions
console.log(`Action: ${target} -> ${method}(${params})`)
// Access triggering element when available
if (element) {
console.log('Triggered by:', element.tagName, element.id || element.className)
}
// Handle special cases
if (target === 'location' && method === 'navigate') {
// Custom navigation logic
window.location.href = params
return true // Prevent default handling
}
return false // Continue with default handling
}
]
})Actions follow the pattern: -> selector/method/params
selector: CSS selector or component namecomponent-name- finds closest component with this tag name#id- finds element by ID.class- finds element by class/- current component (closest custom element)
method: method name to call on the target element/componentparams(optional): comma-separated parameters to pass to the method
prevent- callsevent.preventDefault()stop- callsevent.stopPropagation()sync- executes actions sequentially (awaits each)element- passes the triggering element as first parameter to methods
click,dblclick,contextmenuinput,change,submit,reset,selectkeydown,keyuppointerdown,pointeruptoggle
focusin,focusoutpointerenter,pointerleave
Call the update method on the closest dynamic-section component:
<button data-ed-click="-> dynamic-section/update">Update Section</button>Call a method within the current component (uses closest lookup):
<button data-ed-click="-> /open">Open</button>Execute multiple actions in parallel (default) or sequentially (with sync flag):
<button data-ed-click="
-> component-a/methodA
-> component-b/methodB
-> #specific-element/methodC
">Multiple Actions</button>Use flags for event control and call multiple components:
<button data-ed-click="
prevent, stop, sync
-> dynamic-section/preload
-> #dialog-modal/open
">Open Dialog</button>Ensure actions are executed one after another, waiting for each to complete:
<button data-ed-click="
sync
-> data-loader/fetch
-> chart-component/render
-> notification/show
">Load and Display Data</button>Pass the triggering element as the first parameter to methods:
<custom-form-component>
<form data-ed-submit="prevent -> /submitForm">
<!-- Checkbox state handling -->
<input type="checkbox" data-ed-change="element -> /toggleDetailedForm">
<!-- Notes -->
<fieldset hidden>
<textarea name="note_1"></textarea>
<textarea name="note_2"></textarea>
<!-- Any another fields -->
</fieldset>
<!-- Input validation on change -->
<input
type="email"
data-ed-input="element -> /validate/email"
placeholder="Enter email"
>
<button type="submit">Submit</button>
</form>
</custom-form-component>In your web component:
class CustomFormComponent extends HTMLElement {
toggleDetailedForm = (triggerElement: Element) => {
const input = triggerElement as HTMLInputElement
console.log('Show detailed form: ', input.checked)
// Handler
}
validate = (element: Element, type: string) => {
const input = element as HTMLInputElement
const value = input.value
console.log(`Need to validate ${type}, current value: ${value}`)
// Validator
}
submitForm = () => {
console.log('Form submitting ...')
// Submit logic
}
}- Modern browsers with ES2018+ support
- Custom Elements v1
- Event delegation with capture/bubble phases
MIT
Issues and pull requests are welcome on GitHub.