I've written my own JavaScript class (for a custom web component). It raises a couple of events. For instance: TagChanged
To listen to this event, I (obviously) do this:
myObject.addEventListener('TagChanged'), (e) => doSomething());
But is it possible to have something like:
myObject.onTagChanged = (e) => doSomething();
The default DOM elements have things like onClick
and onKeyDown
. Are they using some other architecture?
default Events
onclick
andonkeydown
. Are they using some other architecture?
Yes, Browser code us mortals can not access
But the Browser also calls a handleEvent
method on a JavaScript class... if a mortal created it
The method addEventListener() works by adding a function, or an object that implements a
handleEvent()
function, to the list of event listeners for the specified event type on the EventTarget on which it's called. If the function or object is already in the list of event listeners for this target, the function or object is not added a second time.
So you can do
this.addEventListener("myEvent", this) // calls 'handleEvent' on 'this' class
which (by default) calls handleEvent
IF you created it!
handleEvent(evt) { // handleEvent called by default
// check if "event_myEvent" method exists on class
// then call as function(evt)
this[ "event_"+evt.type ]?.(evt)
}
Then triggers your method:
event_myEvent(evt) {
// your event handling
}
Note: Events from shadowDOM require bubbles:true, composed:true
to "escape" shadowRoots
customElements.define("handle-event", class extends HTMLElement {
handleEvent(evt) { // handleEvent is called by default on every JavaScript Object!
this["event_" + evt.type]?.(evt) // check if "event_NNN" method exists
}
event_myEvent(evt) {
let div = evt.composedPath()[0] // Event from DIV escaped shadowRoot
div.colors.push(div.style.background = div.colors.shift());
}
connectedCallback() {
this.addEventListener("myEvent", this) // calls 'handleEvent' on 'this' Object/Class by default
const createElement = (tag, props = {}) => Object.assign(document.createElement(tag), props)
const newDIV = (name) => {
const divEvent = new CustomEvent("myEvent", {
bubbles: true,
composed: true, // listener is on <handle-event> not on shadowRoot, needs to escape shadowRoot
detail: {},
})
const div = createElement("div", {
textContent: name,
colors : ["red","yellow","blue"],
onclick: (evt) => div.dispatchEvent(divEvent),
})
return div;
}
this.attachShadow({mode:"open"}).append(
createElement("style", {
textContent: `div { cursor:pointer; background:teal; color:black; padding:10px }`,
}),
...["FOO","BAR","BAZ"].map(newDIV)
)
}
})
Click row to cycle colors
<handle-event></handle-event>