3 ms·
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-temp
by lenkite 4y ago
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.
- blowski 4y ago> With substitution variables/text, this feature could be amazing. At which point, are you just re-creating JavaScript?
- akira2501 4y agoHere'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.
- vidaj 4y agoI 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/b27f1140a8ae711c7df2372c4b5cfeea 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.