polymerpolymer-2.xdom-repeat

Can I use dom-repeat on slotted content to wrap each slotted child inside some tag?


I'd like to use dom-repeat to wrap a bunch of child nodes in <li> tags. The problem is, the nodes I want to repeat are custom elements themselves, inserted via a slot, and it seems that dom-repeat only takes data passed via attributes.

What I want to do is:

<dom-module id="my-custom-element">
  <template>
    <section>
      ...
      <ul>
        <dom-repeat items="{{ TOP-LEVEL NODES IN LIST SLOT }}">
          <template>
            <li>{{ item }}</li>
          </template>
        </dom-repeat>
      </ul>
    </section>
  </template>
</dom-module>

And using it:

<my-custom-element>
  <ul slot="LIST">
    <my-other-custom-element></my-other-custom-element>
    <my-other-custom-element></my-other-custom-element>
    <my-other-custom-element></my-other-custom-element>
  </ul>
</my-custom-element>

Solution

  • I don't think this is the best Polymer way to do it, however it works:

      <x-foo>
        <ul slot="list">
          <div> hi </div>
          <div> hello </div>
          <div> bye </div>
        </ul>
      </x-foo>
    
      <dom-module id="x-foo">
        <template>
          <h2> The raw slotted items </h2>
          <slot name="list" id="list"></slot>
            <h2> The slotted list items wrapped with 'li' </h2>
          <ul id="styledList"></ul>
        </template>
      </dom-module>
    

    Here is the trick:

     class XFoo extends Polymer.Element {
        static get is() { return 'x-foo'; }
    
        static get properties() {
          return {
            items: {
              type: Array,
              value: function() {
                return [1, 2, 3, 4]
              }
            }
          };
        }
    
        connectedCallback() {
          super.connectedCallback();
          this.$.list.addEventListener('slotchange', (e) => this.bindSlottedItems() );
        }
    
        bindSlottedItems() {
            let items = this.$.list.assignedNodes({flatten: true})[0].childNodes;
            items = [].slice.call(items)
            this.$.styledList.innerHTML = items.filter((item) => item.outerHTML).map((item) => {
              return `<li> ${item.outerHTML} </li>`
            }).join('');
        }
      }
      customElements.define(XFoo.is, XFoo);
    

    https://codepen.io/MWalid/pen/aGJRWy