htm icon indicating copy to clipboard operation
htm copied to clipboard

Allow users to register element names

Open dfabulich opened this issue 5 years ago • 2 comments

https://github.com/esxjs/esx looks a lot like HTM, but instead of handling components as <${Foo}>, you have to (get to?) pre-register component names, like this: esx.register({Foo})

Then you can use custom components like this:

esx`<Foo bar=baz>Blah</Foo>`

It would be cool if this were an option for HTM as well.

dfabulich avatar May 04 '20 19:05 dfabulich

You can bind a function works like a proxy to render pre-registered components.

import { h, render } from 'https://unpkg.com/preact?module';
import htm from 'https://unpkg.com/htm?module';

const App = ({ children }) => ['Hello, ', children, '!']

// Imitation of createEsx()
const createEsx = (components) =>
  htm.bind((type, ...rest) => h(components[type] || type, ...rest))

const esx = createEsx({ App })
render(esx`<App>world</App>`, document.getElementById('app'))

yhatt avatar Jan 30 '21 12:01 yhatt

@yhatt exactly! There's also a way to do this for everything rendered by Preact, including elements created via h() and JSX:

import { options, h, render } from 'https://unpkg.com/preact?module';
import htm from 'https://unpkg.com/htm?module';
const html = htm.bind(h);

// component registry
const components = {};
components.App = ({ children }) => ['Hello, ', children, '!'];

// inject component registry into Preact itself:
let old = options.vnode;
options.vnode = vnode => {
  if (vnode.type in components) vnode.type = components[vnode.type];
  if (old) old(vnode);
};

// now it's global!
render(html`<App>world</App>`, document.body);
// or:
render(h('App', {}, 'world'), document.body);

developit avatar Feb 05 '21 03:02 developit