From a5c05026662818ed4815760737c57d7e92b8a78e Mon Sep 17 00:00:00 2001 From: DarkWiiPlayer Date: Mon, 18 Aug 2025 10:41:53 +0200 Subject: [PATCH] Add more examples to readme --- readme.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index bad654f..15b4957 100644 --- a/readme.md +++ b/readme.md @@ -2,6 +2,23 @@ A prototype for an alternative to custom elements. +```js +// example.js +import controllers from "controller-registry" + +controllers.define("clickable", (element, detached) => { + element.addEventListener("click", () => { + alert("The element has been clicked!") + }, detached) +}) +``` + +```html + + + +``` + ## Concept Similar to a custom element, a controller defines custom behaviours for HTML @@ -26,13 +43,63 @@ Controllers can be registered under any name as either a callback which gets called when the controller is added to an element or a constructor which gets called with `new` and passed a revokable proxy to the element. +```js +controllers.define("showcase", class ShowcaseController { + constructor(element, detached) { + this.method(element) + // detached promise is passed here too for convenience, + // but the `detached` method is the preferred place + // to put cleanup code. + } + + method(element) { + console.log("Calling method on:", element) + } + + detached(element) { + // Cleanup if necessary + } +}) +``` + +Note that only class controllers are given a revocable proxy: this is because +their stateful nature and suitability for more complex handling makes them more +likely candidates to retain references to the target past their detachment. + +For complex function controllers, this can easily be done manually using +`Proxy.revocable(element, {})`. + +This behaviour might change in the future. + If the controller is a function, the second argument is a promise that resolves -when the controller is removed again. This promise has an additional property -`"signal"` which returns an `AbortSignal`. This means the promise can be passed -directly as the third argument to `addEventListener` function calls. +to the element when the controller is removed again. This promise has an +additional property `"signal"` which returns an `AbortSignal`. This means the +promise can be passed directly as the third argument to `addEventListener` +function calls. + +```js +controllers.define("showcase", async (element, detached) => { + console.log("Attached to element:", element) + console.log("Detached promise:", detached) + console.log("Detached signal:", detached.signal) + element === await detached + console.log("Detached from element:", element) +} +``` The registry also exposes a `list` function which, given an element, returns an object similar to a `DomTokenList` for easier management of the controller list. The `controller` attribute is a space-separated list of controller names as registered in the registry. + +## Interactions between controllers + +There is no direct way for controllers to interact with each other, as they +should be mostly independent. + +When signalling is needed, events are the way to go; when data needs to be +shared, the element's `dataset` or a more semantic attribute should be used. + +For anything even more complex, a custom element or a higher level component +framework might be the better solution.