Aureliaportal attribute
Lifting your element with ease.
1. Installation
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
<!-- 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>
It could be an issue sometimes when this
Try changing overflown of the box of the left via checkbox above
Or it could be inside an item in a list with
This is an issue no matter what library, framework you use. One way to solve this is to have.item-list {
position: fixed;
}
Instead of having<!-- 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>
The<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>
Following is an example of combobox with
You can see that even with
3. Advanced usage
4. Usage instruction
Basic usage
Most of the time, the usage would be very simple, you annotate the element with a
portal attribute on it and that's all (ex:div ) , even when using together with other template controller attribute like= if .It is recommended to avoid putting
portal on the same element withrepeat , If you do have to, thenportal should come beforerepeat . As they read:portal in beforerepeat : Create a portal at that location, then repeat / create all those items, then move them into there.repeat in beforeportal : for each of those items, put them into the original position in the template, then create portal for each item then move it there.
Life cycle
The
portal attribute exposes some life-cylce hooks to support async action, such as api request/ animation The above snippets of moving player into different room could be extended like following:portal attribute usage with life cyclePositioning portals
Usually it is desired to have the portaled element "stick" next to its original sibling / parent element. While it is more convenient if the
portal attribute packs some more functionalities in it, the requirements could be easily handled via some other library such as Tether (http://tether.io/) or Popper (https://popper.js.org/). Those two libraries also handle advanced cases such as scrolling, flipping, fitting available space well. For simpler / one time position scenarios, a combination ofif & few aurelia onetime offset bindings should be sufficient.
Moving the element easily to different DOM position, without causing any issues to aurelia view hierarchy, should be the main focus of this attribute. However, if you feel there is a good reason to support it out of the box, please open a discussion athttps://github.com/bigopon/aurelia-portal-attribute/issues
5. API
: The element to render to.string will be treated as CSS selector and used to query element viaquerySelector : The context element to find the element to render.string will be treated as CSS selector and used to query element viaquerySelector : Set totrue to throw an error if expected element cannot be found viadocument.querySelector (false by default): The object that will becontext when calling life cycle methods below. By default, it's the custom element view model this attribute resides in. When used inside arepeat , it will be on the fly binding context created byrepeat attribute.Life cycle
: Will be called when the attribute receive new targetafter the first render.: Will be called afterdeactivating has been resolved.: Will be called afterportaled element has been added to target: Will be called afteractivating has been resolved
- Adrian von Ziegler for music
- RPG Awesome & Game icons for icon set
- Jason for api ideas / design