Aureliaportalattribute

Lifting your element with ease.

1. Installation

The plugin contains a singleportalattribute. It helps put your elements dynamically arbitrarily in the document, with same underlying view model, and same bindings wiring between the view / view model.

Installing plugin like the following snippet:
// In your main.js
import { PLATFORM } from 'aurelia-framework';

export function configure(aurelia) {
  // Use PLATFORM.moduleName for webpack
  aurelia.use.globalResources(PLATFORM.moduleName('aurelia-portal-attribute'));
}

2. Problem & solution

Say we have acomboboxelement that has an input, a trigger button to expand the list and a list that contains all item, like the following markup:
<!-- combobox.html -->
<template class="combobox">
  <require from='./combobox.css'></require>

  <div class="input-ct">
    <input ref="input" value.bind="filterText" />
    <button click.delegate='expandList()'></button>
  <div>

  <div class="list-ct">
    <ul show.bind="expanded"
      class="list-group items-list">

      <li repeat.for="item of items | filter: 'name' : filterText"
          class="list-group-item">${item.name}</li>
    </ul>
  </div>
</template>
Depends how you go further from above snippet, it will have different final look. Below is a demo of combobox element:
Choose your character:
 - Level:
  • Andreas the Arakkoa - Level:14
  • Andrew the Nord - Level:59
  • Ashley the Tuskarr - Level:66
  • Bazyli the Saurok - Level:70
  • bigopon the Vrykul - Level:1
  • Bryan the Satyr - Level:81
  • Dwayne The Rock Charrington the Titan - Level:87
  • Erik the Human - Level:88
  • Jason the Titan - Level:60
  • Jeremy the Krogan - Level:9
  • Jeroen the Hozen - Level:45
  • Jods4 the Drell - Level:29
  • Matthew the Mantid - Level:39
  • Patrick the Angara - Level:71
  • Rob the Vrykul - Level:89
  • Shuhel the Imperial - Level:31
  • Strahil the Hozen - Level:8
  • Vildan the Centaur - Level:88
  • Zacherey the Ogre - Level:43

Character selected! Awesome!

It could be an issue sometimes when thiscomboboxelement stays inside of DOM tree withoverflow: hiddenlike the following example, you will see item list got clipped:

This is a 200x200 (px) box that withoverflow: hidden
  • Mournleaf the Dletu
  • Hellaxe the Spleni
  • Warriormorning the Doomtheo
  • Hammerfury the Venwyrm
  • Oakshade the Ferrie
  • Talldawn the Autian
  • Spinebear the Rosa
  • Battlersilver the Syll-mond
  • Breeze the Glitmys
  • Gatemorning the Beatia
  • Daywave the Burllde
  • Treeshinespine the Laxstenn
  • Bloodside the Mike
  • Halfgazer the Zusze
  • Summermoor the Phyma
  • Landgray the Smane
  • Grayplainssummer the Howlron
  • Sandlake the Thonnight
  • Ramboar the Laikaz
  • Cloakmight the Liernaxren

Try changing overflown of the box of the left via checkbox above

Or it could be inside an item in a list withoverflow: autolike the following example:

list withoverflow: auto
Choose dragon 1:
  • Battlersilver the Autian
  • Cloakmight the Syll-mond
  • Bloodside the Laikaz
  • Summermoor the Ferrie
  • Spinebear the Beatia
  • Mournleaf the Smane
  • Treeshinespine the Spleni
  • Hellaxe the Rosa
  • Warriormorning the Dletu
  • Grayplainssummer the Zusze
  • Gatemorning the Liernaxren
  • Talldawn the Doomtheo
  • Breeze the Thonnight
  • Halfgazer the Howlron
  • Ramboar the Venwyrm
  • Oakshade the Mike
  • Sandlake the Phyma
  • Landgray the Burllde
  • Hammerfury the Laxstenn
  • Daywave the Glitmys
Choose dragon 2:
  • Battlersilver the Autian
  • Cloakmight the Syll-mond
  • Bloodside the Laikaz
  • Summermoor the Ferrie
  • Spinebear the Beatia
  • Mournleaf the Smane
  • Treeshinespine the Spleni
  • Hellaxe the Rosa
  • Warriormorning the Dletu
  • Grayplainssummer the Zusze
  • Gatemorning the Liernaxren
  • Talldawn the Doomtheo
  • Breeze the Thonnight
  • Halfgazer the Howlron
  • Ramboar the Venwyrm
  • Oakshade the Mike
  • Sandlake the Phyma
  • Landgray the Burllde
  • Hammerfury the Laxstenn
  • Daywave the Glitmys

Try changing overflown of the box of the left via checkbox above

This is an issue no matter what library, framework you use. One way to solve this is to have

.item-list {
  position: fixed;
}
on the list, this will make it"get out"of its restrictive container, and then calculate the position of the list to put it next to where it should be. But it potentially requires to recalculate the position when user scrolls away.

Instead of havingposition: fixed, we could use the plugin, via addingportalattribute to the list like following example:
<!-- combobox.html -->
<template class="combobox">
  <require from='./combobox.css'></require>
  
  <div class="input-ct">
    <input ref="input" value.bind="filterText" />
    <button click.delegate='expandList()'>▼</button>
  <div>

  <div class="list-ct">
    <!-- With portal attribute -->
    <ul show.bind="expanded"
      portal
      class="list-group items-list">

      <li repeat.for="item of items | filter: 'name' : filterText"
          class="list-group-item">${item.name}</li>
    </ul>
  </div>
</template>
  

Theportalattribute could be an overkill if you only want a simple solution for it via CSS withposition: fixed. However, besides styling, it also helps you separate DOM path of different parts in your custom element, whist still binds them to the same underlying view model, which should helps better DOM manangement, including event model in some cases. Following is an example of final rendered DOM tree forcomboboxabove:
<body>
  <app>
    <combobox>
      <!-- combobox internal elements -->
    </combobox>
  </app>
  <!-- combobox item list in the body -->
  <ul class="list-group items-list">
    <li class="list-group-item">item 1</li>
    <li class="list-group-item">item 2</li>
    <li class="list-group-item">item 3</li>
    ...
    <!-- more items -->
  </ul>
</body>
Note: you still have to calculate position of the list, applyposition: absolute;to it and put it where it should be, but now anyoverflow: hidden/ autoancestor shouldn't be in the way for you to render your combobox.

Following is an example of combobox withportalattribute on item list:

You cannot choose weapons before choosing a character
Weapon
Shield

You can see that even withoverflow: hidden, our item lists can still be seen, because they stay in different path and thus, cannot be clipped by their "ancestors" elements.

3. Advanced usage

You need to select character, weapon and shield before you could continue this section.

4. Usage instruction

5. API

portalattribute@bindableproperties:

Thanks to:

License