Use of containerless

What is best/worse practice of using containerless in view model or in view?
When to use containerless and when not to use containerless?

All this question I have in my mind after conversation I have with @boban.r

1 Like

I’ve used it in SVG where HTML components are not valid. It’s also useful if you want off the shelf CSS to work without modification.

Not an authoritative answer, but to share my experience.

As Aurelia document said, @containerless does fight shadowdom which will be part of html standard, plus other quirks, use it sparingly.

We use @containerless to avoid creating intermediate dom wrapper <my-comp> that destroys inner element styles or position, right? How could we avoid using it as much as possible.

Replace @containerless with as-element

  1. in almost every use cases, you can avoid using @containerless by using
    <ul as-element="my-comp">.
  2. you may ask what about dynamic composition <compose view-model="./my-comp">,
    can I avoid intermediate <compose> tag?
    • well, @containerless cannot fix this, but as-element can.
    • use <ul as-element="compose" view-model="./my-comp">. :scream: :scream: :scream:

You have to use @containerless for svg partial, as-element doesn’t work

Just read Aurelia document. This is limited by browser’s native html parser (which Aurelia uses to parse every html template file), you need a <svg> tag wrap in your svg partial template to teach browser parser you are writing svg, not html. (technically, svg is xml, not html)

But you might be perfectionist

You cannot stand the possibility that fellow developers might misuse your component directly as <my-comp>, then ends up blaming you the broken style/layout. How to ensure the usage of as-element?

Now you can shout back: “Read your console log, dumb ass!”.

import {inject} from 'aurelia-framework';

@inject(Element)
export class MyComp {
  constructor(element) {
    if (element.tagName === 'MY-COMP') {
      throw new Error("cannot use <my-comp>. use <other-tag as-element=\"my-comp\">.");
    }
    
    if (element.tagName === 'COMPOSE') {
      throw new Error("cannot use <compose view-model=\"my-comp\">. use <other-tag as-element=\"compose\" view-model=\"my-comp\">.");
    }
  }
}
import {inject} from 'aurelia-framework';

@inject(Element)
export class MyTableRow {
  constructor(element) {
    if (element.tagName !== 'TR') {
      throw new Error("use <tr as-element=\"my-table-row\">.");
    }
  }
}
6 Likes

Just want to show one more off-topic tip, you can avoid intermediate <router-view> tag.

 <div class="row" as-element="router-view"></div>

Don’t be too surprised. compose and router-view are just custom elements, not much different from those you defined.

6 Likes

A good example of usage will be when you have list item as a component nested in list and you won’t break the style: ul > li { // CSS }
<ul>
<list-item>
<list-item>
…
</ul>

2 Likes

just out of curiosity :smile:, can we use as-element on <template> tag too?

<template as-element="my-custom-element">

</template>

I cannot test it right now :smile:

@huochunpeng <compose containerless></compose> works . I’m using it in a couple of places without issue.

This also works:
<router-view id="main-router" containerless></router-view>

3 Likes

Well this is black magic of semantic markup (-:

this qoute from docs makes total sense:

Note that when a containerless attribute is used, the container is stripped after the browser has loaded the DOM elements, and as such this method cannot be used to transform non-HTML compliant structures into compliant ones!

For example

<select name="" id="">
    <template repeat.for="">
        <option value=""></option>
    </template>
</select>

does not work in ie

1 Like

I really appreciate what all of you write. Until this moment everywhere I use as-element but I was curious what @containerless do.
While creating one CE and using in table I figure that you need to use as-element=“table-head” because only like this browser knows how to render your CE.

So to sum up if I can (please correct me if I’m wrong :smiley: )

  • use @containerless for SVG — removing custom element tag is happening after browser render all html
  • use as-element almost everywhere

I’d add : if you control markup - as-element is more compatible at the moment. with less styling needed.

Recently faced the need to use containerlesscustom elements. I just want to point out that if you want to use your custom element with all the glory of binding, but don’t want to have the wrapping DOM element, then containerless attribute is the best choice.

<my-element prop1.bind="value" containerless></my-element>

This makes specific instances of my-element container-less, without impacting all instances of my-element.

4 Likes

I know this is an old topic, but wanted to add the usefulness of containerless.

I’m working on a solution that dynamically creates Bootstrap toolbar buttons based on a JSON config file. There are instances where I have to do something like <div if.bind or <div repeat.for. These are only needed to make decisions and I don’t need actually need them in the final HTML. Because Bootstap button groups look different based on which elements are direct children or descendants these extra divs were making the UI look bad. Turning those divs into a custom element that’s containerless solved the problem for me. BTW, if you know of a better way of doing this let me know, lol!

Can I take an aside and just say how much I like Aurelia. I’ve been using it for a few years now and I’m amazed at how simple it’s able to solve problems I run into, like the above mentioned one. I feel like you just need to learn a few basic principles and that’s all you need, don’t need to learn all this special syntax like with some other frameworks.

I do think documentation could be better though. I had no idea containerless could be used directly in an HTML only custom element as the documentation only used it with a view-model. It was only by searching this thread that I saw I could use it as an HTML attribute. That one discovery completely changed I approached this problem. In any case, it is an awesome framework and wanted to give a note of appreciation to the creators/maintainers for a job well done in architecting it.

5 Likes