dimlucas dimlucas - 2 months ago 31
TypeScript Question

Variable Number of Slots in Aurelia

I want to create a custom element that's going to work like an accordion container for other elements. I'm planning on using the Bootstrap 4 Collapse. I want to be able to place a variable number of other custom elements within it so using slots is not enough.

For example if I knew that there will be 3 elements placed in the accordion I would put three slots in accordion.html and then use it like this:

<accordion>
<first-custom-element slot="first-element"></first-custom-element>
<second-custom-element slot="second-element"></second-custom-element>
<third-custom-element slot="third-element"></third-custom-element>
</accordion>


The thing is, I don't know how many elements will need to placed inside the accordion because I want to make it more generic and reusable so I can use it in multiple pages in my application. What I want is a way to read everything placed inside the
<accordion>
tags and create slots for each one of these elements the fly. Is there such a functionality in Aurelia or should go for a custom implementation?

Answer

Split out the items from the overall accordion element, like this:

accordion.html

<template>
  <div id="accordion" role="tablist" aria-multiselectable="true">
      <slot></slot>
  </div>
</template>

accordion-item.html

<template bindable="panelTitle, headingId, itemId">
  <div class="panel panel-default">
    <div class="panel-heading" role="tab" id="${headingId}">
      <h4 class="panel-title">
          <a data-toggle="collapse" data-parent="#accordion" href="#${itemId}" aria-expanded="true" aria-controls="${itemId}">
            ${panelTitle}
          </a>
        </h4>
    </div>
    <div id="${itemId}" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="${headingId}">
      <slot></slot>
    </div>
  </div>
</template>

Usage

<template>
    <require from="accordian.html"></require>
    <require from="accordian-item.html"></require>

    <accordian>
        <accordian-item panel-title="Panel 1 Title" heading-id="headingOne" item-id="collapseOne">
            <accordian item 1 content>
        </accordian-item>
        <accordian-item panel-title="Panel 2 Title" heading-id="headingTwo" item-id="collapseTwo">
            <accordian item 2 content>
        </accordian-item>
    </accordian>
</template>