`deka-dom-el` — Scopes and components

Organizing UI into components

Using functions as UI components

For state-less components we can use functions as UI components (see “Elements” page). But in real life, we may need to handle the component live-cycle and provide JavaScript the way to properly use the Garbage collection.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js import { scope, el, on } from "deka-dom-el"; /** @type {ddeElementAddon} */

The library therefore use scopes to provide these functionalities.

# Scopes and hosts

The host is the name for the element representing the component. This is typically element returned by function. To get reference, you can use scope.host() to applly addons just use scope.host(...<addons>).

import { el, on, scope } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; const { host }= scope; host( element=> console.log( "This represents Addon/oninit for root", element.outerHTML ) ); console.log( "This represents the reference to the host element of root", host().outerHTML ); document.body.append( el(component) ); function component(){ const { host }= scope; host( element=> console.log( "This represents Addon/oninit for the component", element.outerHTML ) ); const onclick= on("click", function(ev){ console.log( "This represents the reference to the host element of the component", host().outerHTML ); }) return el("div", null, onclick).append( el("strong", "Component") ); }

To better understanding we implement function elClass helping to create component as class instances.

import { chainableAppend, el, scope } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; class Test { constructor(params){ this._params= params; } render(){ return el("div").append( this._params.textContent ); } } document.body.append( elClass(Test, { textContent: "Hello World" }) ); function elClass(c, props, ...addons){ let element, element_host; scope.push({ scope: c, //just informative purposes host: (...c)=> c.length ? (!element ? addons.unshift(...c) : c.forEach(c=> c(element_host)), undefined) : element_host }); const C= new c(props); element= C.render(); const is_fragment= el instanceof DocumentFragment; const el_mark= el.mark({ //this creates html comment `<dde:mark …/>` type: "class-component", name: C.name, host: is_fragment ? "this" : "parentElement", }); element.prepend(el_mark); if(is_fragment) element_host= el_mark; chainableAppend(element); addons.forEach(c=> c(element_host)); scope.pop(); return element; }

# Mnemonic