Scott Whittaker

Frontend Developer

Day job React | side projects Svelte

Aurelia - Data Driven Dynamic Views

If you are not familiar with Aurelia head on over to the documentation and take a look at the Getting Started section. It is a very compelling framework. I am willing to bet that if you have used other modern frameworks you will find Aurelia a breeze to get going and may want to use it as your framework of choice right now. Once you are up and running Aurelia has an almost intuitive quality thanks to its adherence to standards.

Heterogeneous Views

Rendering different views into the DOM is straightforward with Aurelia. It is a common requirement to display a list or grid of items that differ in context and should have a different design so that users can easily distinguish between them. For example, when using your favourite catch up TV service you often find a grid with tiles of different sizes; larger tiles may infer a promoted or featured item, smaller tiles may be used for regular content. These views are often referred to as heterogeneous - diverse in character or content.

Take this example from BBC iPlayer. It has a list on the left hand side, a large featured item in the centre and 2 smaller, regular content items on the right.

Example content grid from BBC iPlayer

Example

Head over to this Plunker if you want see the example or dive into the code and mess around.

Data

To demonstrate how to render different views based on data using Aurelia we will use the following JSON data to simulate a request to some API.

{
  "citation": {
    "text": "Aurelia Docs",
    "url": "http://aurelia.io/docs.html"
  },
  "quote": "The compose Custom Element enables you to dynamically render UI into the DOM. Imagine you have a heterogeneous array of items, but each has a type property which tells you what it is.\r\n",
  "type": "quote"
}, {
  "title": "Standard Media Tile",
  "picture": "http://placehold.it/104x104",
  "description": "Cupidatat ad duis minim officia sint aute consectetur irure minim.\r\n",
  "type": "standard"
}, {
  "title": "Feature Media Tile",
  "picture": "http://placehold.it/424x208",
  "description": "Nisi occaecat ullamco consectetur tempor do nulla aute dolore eiusmod sunt eiusmod duis. Eu id non ipsum deserunt do enim et nostrud cillum ex ea magna deserunt est. Nostrud occaecat reprehenderit in velit veniam magna cupidatat dolor enim fugiat cillum. Lorem culpa exercitation ullamco elit culpa sit. Ut fugiat aliquip cillum mollit cillum tempor. Mollit veniam sint ipsum id nostrud adipisicing cillum tempor. Ex aliqua quis reprehenderit nostrud ullamco consequat.\r\n",
  "type": "feature"
}

Notice that there are 3 different values for type: quote | standard | feature. We will create an html template for each of these views as follows…

  • media-quote.html
  • media-standard.html
  • media-feature.html

For each of these types we will render the corresponding html template in a list.

Rendering the Views

We will assume we are rendering our list on a Home page. In Aurelia you create a .js file and a corresponding .html file with the same name in order to create a model and a view respectively.

  • home.js - the model
  • home.html - the view

Model

In the model we fetch data in the activate function and assign it to a variable data. The activate function is one of the Screen Activation Lifecycle hooks and is called before the view is displayed. The data variable will be available to us in the view so that we can render data to the screen.

// home.js

import { inject } from 'aurelia-framework';
import { HttpClient } from 'aurelia-fetch-client';

let url = './data.json';

@inject(HttpClient)
export class Home {
	data = [];

	constructor(http) {
		this.http = http;
	}

	activate() {
		return this.http
			.fetch(url)
			.then((response) => response.json())
			.then((response) => {
				this.data = response;
			});
	}
}

View

<!-- home.html -->

<template>
	<h2>Home</h2>
	<div repeat.for="item of data">
		<compose view="media-${item.type}.html" containerless></compose>
	</div>
</template>

In the view we use a repeater to iterate through the array of objects in data that was defined in the model. For each iteration, a local variable item is assigned the value of the current item in the array. In our example, this means that in the first iteration of the repeater, item will be assigned the following data…

{
	"citation": {
		"text": "Aurelia Docs",
		"url": "http://aurelia.io/docs.html"
	},
	"quote": "The compose Custom Element enables you to dynamically render UI into the DOM. Imagine you have a heterogeneous array of items, but each has a type property which tells you what it is.\r\n",
	"type": "quote"
}

Notice the compose element in the repeater. The compose element enables us to include other views within our current view. For this example we use the view attribute to specify the name of the view and we determine the view file name by using the value of item.type. The ${} syntax is string interpolation, this allows us to build up our file name dynamically from data.

<compose view="media-${item.type}.html" containerless></compose>

Thus, for each iteration of the repeater a different view is ‘composed’ based on the type value defined in the data.

<div repeat.for="item of data">
	<!-- 1st iteration -->
	<compose view="media-quote.html" containerless></compose>
	<!-- 2nd iteration -->
	<compose view="media-standard.html" containerless></compose>
	<!-- 3rd iteration -->
	<compose view="media-feature.html" containerless></compose>
</div>

Take a look at the example.

Conclusion

Nothing much more to say other than it is very easy to compose data driven views with Aurelia.