• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

I Like Kill Nerds

The blog of Australian Front End / Aurelia Javascript Developer & brewing aficionado Dwayne Charrington // Aurelia.io Core Team member.

  • Home
  • Aurelia 2
  • Aurelia 1
  • About
  • Aurelia 2 Consulting/Freelance Work

Aurelia Dynamic Composition

Aurelia 1 · October 23, 2015

One of my favourites parts of Aurelia is the compose element which allows you to dynamically render UI into the DOM. It is especially handy in situations where you want to dynamically render ViewModels inside of a loop like widgets or other dynamically composed elements.

Containerless <compose>

One of the lesser known features of the compose element is the ability to specify a containerless attribute on the element. By default if you use the compose element your page will feature the element with the rendered contents inside.

Sometimes you don’t want the compose element just the contents rendered inside because you might be using it to render table rows or parts in the DOM where the compose element would break the layout.

<template>
    <div repeat.for="widget of widgets">
        <compose view-model="widgets/${widget.type}.js" containerless></compose>
    </div>
</template>

This would render the contents of the composed view minus the compose element, cool huh?

ViewModel-less <compose>

Sometimes you might just want to render a HTML View and not concerned with ViewModel data. Using the view attribute we can render custom views without needing to specify anything else.

In the below example if the widget type property is “table” then the view loaded would be: table-view.html – as you can see we can dynamically compose views without needing to pass in a ViewModel. This means the composed elements becomes databound to the surrounding context which is embedding the element.

<template>
    <div repeat.for="widget of widgets">
        <compose view="${widget.type}-view.html"></compose>
    </div>
</template>

Supply data via view-model to <compose>

What good would being able to render custom components into your DOM be if you couldn’t pass in data as well? Using the model attribute we can pass in an object of data which becomes available in the ViewModel of our composed View.

Assuming our widget objects have a data attribute which has an object of data, we can specify our compose element passes through this data so it can be used within the view. You can also pass through a Javascript class filename to view-model which allows you to use lifecycle methods like activate (which gets the data as its first argument as an object) inside of your ViewModel.

<template>
    <div repeat.for="widget of widgets">
        <compose view="${widget.type}-view.html" model.bind="widget.data"></compose>
    </div>
</template>

Accessing model.bind data

To get data passed through to a &lt;compose&gt; element, you can specify a canActivate or activate method inside of your viewmodel and the first parameter gives you the supplied model.

export class MyViewModel {
    activate(model) {
        // model is the passed through object
    }
}

Conclusion

We are only scratching the surface here. If you want more information on using compose to suit your needs, feel free to leave a comment for more advice and usage examples.

Dwayne

Leave a Reply Cancel reply

8 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Morio
Morio
6 years ago

Great post. Would like to see this kind of article in official documentation.

0
Mik
Mik
6 years ago

Hi, first thank you for the great articles about aurelia. I have a question about compose views. For simplicity say I have a view + Model with a simple text inputfield. When I render this view several times in my “parent”-view, I get several inputfields which are independently. But when I typed different text in these fields, where are the data stored? I have only one binding to one class/model.

0
4imble
4imble
6 years ago

With the ViewModel-less compose I had to prefix my view with a relative path (./) like so: “ or I was getting the classic`h.load`error

0
David
David
5 years ago

Thanks for this great post!
Just found one little mistake in chapter “Supply data via view-model to “:
In the example you pass the model to a ViewModel-less :

It would be great, if this would work and i could simply get to my data in the ViewModel-less via ${model.MyWidgetData}, but sadly not.
I think this line is correct here (?):

0
David
David
5 years ago

And again:
Thanks for this great post!
Just found one little mistake in chapter “Supply data via view-model to “:
In the example you pass the model to a ViewModel-less :
compose view=”${widget.type}-view.html” model.bind=”widget.data”
It would be great, if this would work and i could simply get to my data in the ViewModel-less via ${model.MyWidgetData}, but sadly not.
I think this line is correct here (?):
compose view-model=”${widget.type}” model.bind=”widget.data”

0
allen joslin
allen joslin
4 years ago

I cannot make this work now (3/2018) in an app generated using the CLI – esnext & webpack

I got it to work by using view-model.bind & model.bind — but all the widgets are copies of the last widget

Would you be able to update this article?

0
Brian
Brian
4 years ago

Any way to get to the actual view model object that was created? At least, any support way that is exposed through a public api? I see that it’s possible to do compose.ref=”myComposeReference” and then call this.myComposeReference.currentViewModel. But currentViewModel isn’t part of any of your public apis.

0

Primary Sidebar

Popular

  • Testing Event Listeners In Jest (Without Using A Library)
  • How To Get The Hash of A File In Node.js
  • Waiting for an Element to Exist With JavaScript
  • Thoughts on the Flipper Zero
  • How To Get Last 4 Digits of A Credit Card Number in Javascript
  • How To Paginate An Array In Javascript
  • How To Mock uuid In Jest
  • How to Copy Files Using the Copy Webpack Plugin (without copying the entire folder structure)
  • Reliably waiting for network responses in Playwright
  • Wild Natural Deodorant Review

Recent Comments

  • Dwayne on Is Asking Developers How to Write FizzBuzz Outdated?
  • kevmeister68 on Is Asking Developers How to Write FizzBuzz Outdated?
  • Kevmeister68 on Start-Ups and Companies That Embrace Work From Anywhere Will Be More Likely to Survive the Coming Recession in 2023
  • kevmeister68 on What Would Get People Back Into the Office?
  • Dwayne on PHP Will Not Die

Copyright © 2023 · Dwayne Charrington · Log in

wpDiscuz