snuggsi icon indicating copy to clipboard operation
snuggsi copied to clipboard

nested templates

Open etm opened this issue 5 years ago • 5 comments

I think nested template support would be useful.

<template>
  <template name="config">
     <div id="{#}">
       Item {test}
       <template name="even">
         <span>(even {self})</span>
       </template>
       <template name="odd">
         <span>(odd {self})</span>
       </template>
     </div>
  </template>
</template>

with config defined as

get config() {
   return [ { test: "One", odd: true }, { test: "Two", even: true } ] 
}

could render

<div id="0">
  Item One <span>(odd true)</span>
</div>
<div id="1">
  Item Two <span>(even true)</span>
</div>

This would allow for conditional rendering and improve flexibility ;-)

etm avatar Mar 01 '19 20:03 etm

my proposal is to put it in the tokenize function of Template, as shown below (js version). Its the seven lines between "CALL TEMPLATE RECURSIVE START/END". It is tested, works well and is very helpful for many of my more complicated use-cases.

I would create a pull request but i couldn't get the bin/compile script to work (on an unmodified snuggsi), and i don't fully understand your ES coding conventions.

Please consider inclusion in the next release.

var Template = function (template) {

  ...

  function tokenize (context, index) {

    var
      clone = fragment.cloneNode (true)

    typeof context != 'object'
      && ( context  = { self: context })

    context ['#'] = index

    void (new TokenList (clone))
      .bind (context)

    /****** CALL TEMPLATE RECURSIVE START ******/
    for (var tmp of clone.querySelectorAll("template")) {
      var name = tmp.getAttribute('name')                                                                                                                                     
      if (context[name]) {
        var temp = Template(tmp)
        temp.bind(context[name])
      }
    }
    /****** CALL TEMPLATE RECURSIVE END ******/

    return clone
  }

...

}

etm avatar Mar 15 '19 21:03 etm

Of course

get config() {
   return [ { test: "One", odd: { bar: 1 } }, { test: "Two", even: { foo: 2 } } ];
}

works as well (as expected, principle of least surprise) and yields

<div id="0">
  Item One <span>(odd 1)</span>
</div>
<div id="1">
  Item Two <span>(even 2)</span>
</div>

based on the following slightly modified template

<template>
  <template name="config">
     <div id="{#}">
       Item {test}
       <template name="even">
         <span>(even {foo})</span>
       </template>
       <template name="odd">
         <span>(odd {bar})</span>
       </template>
     </div>
  </template>
</template>

etm avatar Mar 15 '19 21:03 etm

@etm interesting as we are having same conversation over at WHATWG. Glad you provided an example. Thanks!

snuggs avatar Mar 18 '19 21:03 snuggs

I'm not sure if there are any scary implications to this, but I think the concept could be useful.

brandondees avatar Aug 15 '19 00:08 brandondees

Add reference updates to template parsing from WHATWG DOM:

  • https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Template-Instantiation.md
  • https://html.spec.whatwg.org/multipage/scripting.html#the-template-element
  • https://html.spec.whatwg.org/multipage/parsing.html#stack-of-template-insertion-modes
  • https://github.com/w3c/webcomponents/issues/704
  • https://github.com/componentkitchen/template-instantiation

snuggs avatar Feb 20 '20 05:02 snuggs