News for hackers. Stuff that matters.
Re:Templating in HTML by lenkite on Wednesday October 05, 2022 @03:27AM (#33092353)
I wish HTML and not just JS had supported for consuming templates. That is I wish we could do variants of:

    1. Define Template using <template id="card-template">...</template>
    2. Consume Template using <use-template id="card1" refid="card-template">..</use-template>
    
With substitution variables/text, this feature could be amazing.
Re:Templating in HTML by blowski on Wednesday October 05, 2022 @03:33AM (#33092410)
> With substitution variables/text, this feature could be amazing.

At which point, are you just re-creating JavaScript?

Re:Templating in HTML by dspillett on Wednesday October 05, 2022 @06:54AM (#33093755)
Not quite, I think he is taking about a more declarative approach compared to that offered by vanilla JS.
Re:Templating in HTML by vbezhenar on Wednesday October 05, 2022 @11:26AM (#33096792)
But works with disabled JS.
Re:Templating in HTML by akira2501 on Wednesday October 05, 2022 @03:51AM (#33092541)
Here's what I got:

    const $template = function(template) {
        // make copy of template content
        const root = template.content.cloneNode(true);
        
        // create proxy object for accessing named nodes and root
        const obj = {
                get $root() {
                        // after template root is called, remove this getter function
                        delete obj.$root;
                        
                        // return root only once
                        return(root);
                }
        };
        
        // find all named template nodes and add to proxy object
        for (const node of root.querySelectorAll('[data-tmpl-name]'))
                obj[node.dataset.tmplName] = node;
                
        // otherwise create template node content wrapped in proxy which
        // makes attempts to overwrite properties an error.
        return(new Proxy(obj, {
                set: () => { throw (new Error(`Attempt to overwrite a template node!`)); }
        }));
    }
    
You can use it with something like:

    <template id="some_id">
        <div>
            <h3 data-tmpl-name="header"></h3>
            <h5 data-tmpl-name="title"></h5>
        </div>
        <p data-tmpl-name="info"></p>
    </template>
And then just:

    function of_some_sort() {
        const t = $template(document.getElementById('some_id'));
        
        t.header.innerHTML = 'The Header';
        t.title.innerHTML = 'The title';
        
        t.info.innerHTML = 'More stuff.';
        
        document.body.append(t.$root);
    }
    
This is was the first version I made. It's not hard to get from here to a version that can fill the template with a data object for you. In my most recent version, you could do:

    function of_another_sort() {
        document.body.append($template(document.getElementById('some_id'), {
            header: 'The Header',
            title:  ['first title', 'second title'],
            
            info: (elem) => {
                elem.setAttribute('functions', 'work');
                elem.innerHTML = 'and receive the internal element itself.';
            }
        }));
    }
    
Arrays duplicate the internal element and make copies of it, objects recurse into the element building a 'key.path.name' while looking for data-tmpl-name to replace. Functions get a copy of the element for more than just innerText/innerHTML replacement. A null or false value eliminates the internal element, and a true value passes it through unchanged.

If you've ever used the old ruby library Amrita, it's basically that, but for HTML Template elements. You can easily do all this in about 100 lines of JS.

Re:Templating in HTML by vidaj on Wednesday October 05, 2022 @07:05AM (#33093827)
I just tested out how to use template with slots, and it was as you said quite simple.

Made a simple gist: https://gist.github.com/vidaj/b27f1140a8ae711c7df2372c4b5cfe... It supports using templates as slot content and updating only the slots you want. Add in some event listeners, and you got basic binding support.