Aurelia 2 has some awesome templating features that make creating dynamic and replaceable components a breeze. One of these features is the au-slot tag. This magic tag, combined with expose.bind and repeaters brings about a new level of control and flexibility for developers to create customizable components.
In Aurelia 2 there are two types of slots: and – the element is only for Shadow DOM-enabled components, whereas the element is more akin to replaceable parts in Aurelia 1 (it’s what they are now in v2).
In Aurelia 1, you could access the controller of an Aurelia component by accessing au.controller of an element. In Aurelia 2, there is a better way using the CustomElement.for method, which provided an element with a controller that will return it.
const dialogController = CustomElement.for(host.querySelector(".my-component") as HTMLElement); const dialogVm = dialogController.viewModel; You can also access a property on the element if you prefer using: element.$au['au:resource:custom-element'] – but the provided method might save you the hassle of having to type things if you’re working with TypeScript.
One of my favourite additions to Aurelia 2 is app tasks. These are framework-level entry points designed to allow you to run code at different points of the framework life cycle.
Recently, while porting over an Aurelia 1 application to Aurelia 2, I encountered a unique use case where code was being run inside configureRouter to asynchronously fetch data from an API to provide metadata for routes.
In Aurelia 2’s @aurelia/router package, you set routes using a decorator or a static routes property. How on Earth do you run code that touches the routes before the router gets them?
When migrating an Aurelia 1 application to Aurelia 2 recently, I had to deal with many routes I needed to convert tediously. As you might have discovered, the Aurelia 2 @aurelia/router is different to the Aurelia 1 router.
Not wanting to change 50+ manual PLATFORM.moduleName values, I opted for a regular expression. I hate RegEx because I don’t understand it, but you cannot deny its power. Here’s the solution I used.
In Aurelia 1, you could access the controller and ViewModel of an element using au.controller and in Aurelia 2, it’s more of the same (except the properties are different). Here is how you get the controller and ViewModel of an element in Aurelia 2.
import { Controller, ICustomElementViewModel } from "aurelia"; // Define an interface for Aurelia element export interface AuElement extends Element { $au: { "au:resource:custom-element": Controller; }; } /\*\* \* This function receives an element and extracts the Aurelia controller associated with it. \* @param {Element} element - The target element \* @returns {Controller|null} - The controller or null if it does not exist \*/ export function getElementController(element: Element): Controller | null { const auElement = element as AuElement; if (!auElement.$au) { return null; } return auElement.$au['au:resource:custom-element']; } /\*\* \* This function gets the View Model associated with a given element. \* @param {Element} element - The target element \* @returns {T|null} - The View Model or null if it does not exist \*/ export function getElementViewModel(element: Element): T | null { const controller = getElementController(element); return controller ? controller.viewModel as T : null; }
The Aurelia 2 makes command ships with the option to scaffold applications and plugins. However, the plugin scaffold uses Webpack and a bunch of dependencies for building plugins. There are reasons that the plugin skeleton uses Webpack.
Firstly, HTML imports need to be inlined in bundled code or you’ll encounter issues with HTML files not being supported by Aurelia conventions when you consume them in your plugins. The same thing applies to CSS styles, you’ll want to inline those as strings too.
Over the last few years, I have created a few plugins for Aurelia, mostly for Aurelia 1. However, with Aurelia 2 on the horizon (possibly released if you’re reading this in the future), I have decided to clean house and adopt a new strategy.
My approach has always been to put my plugins into separate repositories. In my mind, separating issues/pull requests and code made it easier. In reality, having a lot of repositories is a maintenance nightmare.
In this video, I compare some basics like reactivity, component creation and events in Aurelia 2 and Svelte. You’ll notice some similarities between the two but a few differences in the approach to bindables and component creation.
Because I love punishing myself and loading my plate with more things, I have embarked on a new Aurelia 2 series called Building with Aurelia 2. During this series, viewers will see how easy and fun it is to build Aurelia 2 user interfaces and applications.
Since developers have many choices when it comes to frameworks and libraries, I figured a series where developers are shown with real examples of how easy it is to build with Aurelia 2 would be better than more blog posts telling you how great it is.
Dynamic composition is a crucial part of developing robust user interfaces in Aurelia. If you worked with the compose element in Aurelia 1, you might (or might not have) needed to obtain a reference to the composed view-model itself.
While Aurelia 2 keeps many things the same, how dynamic composition works is a little different. We have the new au-compose custom element, which allows us to achieve the dynamic composition of components, including passing data into them.