Events
This page describes how events are used in DDI.
Dispatch events
Dispatch events using dispatchDDIEvent.
Click these and inspect the console
<script>
import { dispatchDDIEvent } from "@dynamic-type/ddi/client";
declare global {
interface GlobalEventHandlersEventMap {
"example:click": CustomEvent<string>;
}
}
for (const button of document.querySelectorAll<HTMLButtonElement>(
"[data-message]",
)) {
button.addEventListener("click", (_e) => {
dispatchDDIEvent(
button,
"example:click",
button.dataset.message ?? "No message",
);
});
}
document.addEventListener("example:click", (e) => {
console.log("message", e.detail);
});
</script><div class="x-flow mbs">
<button data-message="A">A</button>
<button data-message="B">B</button>
</div>The EventBus and global events
Normal events are good when a parent reacts to child events. One way to make children react to a parent is to use global events.
Click this and inspect the console
<script>
import { eventBus } from "@dynamic-type/ddi/client";
declare module "@dynamic-type/ddi/client" {
interface EventBusEventMap {
"example:ping": { ts: Date };
}
}
eventBus.on("example:ping", (payload) => {
console.log("PONG", payload.ts);
});
document
.querySelector<HTMLButtonElement>("[data-ping]")!
.addEventListener("click", () => {
eventBus.dispatch("example:ping", { ts: new Date() });
});
</script><button data-ping="true">Ping</button>Delegated events
DDI has a powerful system for handling delegated events. It is used by Drawer, EventObserver and the consent handler. You can make some eventlisteners prioritized. This advanced behavior is used by the consent handler to disallow some events to happen if no consent has been given.
The event handler can be async, but it is not blocking.
Click and observe
<script>
import { delegatedEventListener } from "@dynamic-type/ddi/client";
const delegator = document.getElementById("delegator")!;
delegatedEventListener(
"click",
(element, event) => {
if (!element.hasAttribute("data-react")) return false;
console.log("We reacted to event from", event.target);
return true;
},
{ attachedTo: delegator, priority: 300 },
);
delegatedEventListener(
"click",
(element, event) => {
if (!element.hasAttribute("data-noisy")) return false;
console.log("We reacted to event from!!!!!!!!!!!!", event.target);
return true;
},
{ attachedTo: delegator, priority: 500 },
);
const wait = (milliseconds: number) =>
new Promise((resolve) => setTimeout(resolve, milliseconds));
delegatedEventListener(
"click",
async (element, event) => {
if (!element.hasAttribute("data-block")) return false;
console.log("start handler");
await wait(3000);
console.log("handler finished", event.target);
return true;
},
{ attachedTo: delegator, priority: 800 },
);
</script><div id="delegator" class="box p:airy flow">
<button data-react="true"><span>A</span></button>
<button data-react="true" data-noisy="true"><span>B</span></button>
<button data-block="true"><span>C</span></button>
</div>CustomElement and events
Add events to observedEvents if you want them to be handled automatically. Eventhandlers will be registered and deregistered.
Click and observe
<script>
import { CustomElement } from "@dynamic-type/ddi/client";
customElements.define(
"ddi-click-observer",
class extends CustomElement {
classes = "";
observedEvents = {
click: (_e: GlobalEventHandlersEventMap["click"]) => {
console.log("Was hit!");
},
};
},
);
</script><ddi-click-observer>
<button>Hit me!</button>
</ddi-click-observer>EventBus
The eventBus is also available on a CustomElement.
Click and observe
<script>
import {
CustomElement,
eventBus,
type EventBusEventMap,
} from "@dynamic-type/ddi/client";
declare module "@dynamic-type/ddi/client" {
interface EventBusEventMap {
"example:ping2": { ts: Date };
}
}
customElements.define(
"ddi-bus-click-observer",
class extends CustomElement {
classes = "";
observedEvents = {
click: (_e: GlobalEventHandlersEventMap["click"]) => {
this.dispatchGlobalEvent("example:ping2", {
ts: new Date(),
});
},
};
observedGlobalEvents = {
"example:ping2": ({
ts,
}: EventBusEventMap["example:ping2"]) => {
console.log("WAS HIT", ts);
},
};
},
);
eventBus.on("example:ping2", ({ ts }) => {
console.log("Global", ts);
});
</script><ddi-bus-click-observer>
<button>Hit me!</button>
</ddi-bus-click-observer>