I know, I just can’t keep quiet about Aurelia. But it is one of the most exciting things to happen to Javascript in a long time. So I decided to write up a quick tutorial on creating a custom element in Aurelia for Select 2, which is a popular library for adding custom select elements to your applications.
Prep
Before we begin, you need to have Aurelia installed locally and the development server running. The easiest way to do this is to download the Aurelia Skeleton Navigation project and follow the README instructions. This tutorial assumes you already have an Aurelia project and that you’re not starting from scratch.
Once you have the Skeleton Navigation project downloaded (or your local project) and all dependencies installed, we need to download Select 2. This can be achieved by opening up a terminal window in your project directory and typing jspm install select2
after the download is finished, the needed changes will be made to the config.js and package.json files.
Now we need to make sure we have jQuery installed as well. This can be achieved by typing in your terminal/PowerShell window: jspm install jquery
– okay, now we have everything that we need to continue.
Creating our custom element
In the src
directory we want to create a folder called resources
and in it create two files: custom-select.js
and custom-select.html
(One is our ViewModel and the other is the View).
In custom-select.js
Let’s focus on the Javascript part of our custom select first. Open up the file custom-select.js
and add in the following:
// Aurelia Framework specific functionality
import {bindable, inject, customElement} from 'aurelia-framework';
// Import JSPM modules we installed earlier
import $ from 'jquery';
import 'select2';
import 'select2/css/select2.css!'
@customElement('select2') // Define the name of our custom element
@inject(Element) // Inject the instance of this element
export class CustomSelect {
@bindable name = null; // The name of our custom select
@bindable selected = false; // The default selected value
@bindable options = {}; // The label/option values
constructor(element) {
this.element = element;
}
// Once the Custom Element has its DOM instantiated and ready for binding
// to happenings within the DOM itself
attached() {
$(this.element).find('select')
.select2()
.on('change', (event) => {
let changeEvent;
if (window.CustomEvent) {
changeEvent = new CustomEvent('change', {
detail: {
value: event.target.value
},
bubbles: true
});
} else {
changeEvent = document.createEvent('CustomEvent');
changeEvent.initCustomEvent('change', true, true, {
detail: {
value: event.target.value
}
});
}
this.element.dispatchEvent(changeEvent);
});
}
}
We are creating our custom element using a decorator called @customElement()
then specifying the tagname. This decorates our class with the require metadata Aurelia needs to know this is our custom element and what the element will look like when referenced in the DOM.
We are also using @bindable
which allows us to specify properties of our custom element which are bindable. We are using the default use of @bindable
but if you read the documentation, you can go deeper and customise many aspects of how a value is bound (one-way, one-time, two-way), callback functions and more.
More notably you can see we are triggering an event on the element itself (at the bottom of the Javascript file above). When I first started with Aurelia I was passing callback functions, with a parameter called callback
however, I encountered far too many issues which was a sign that it was not the right way to go about it.
I have been using React.js since it practically debuted and I became used to the concept of passing callback functions. Triggering events on the element is cleaner and allows us to specify a custom event listener on the element itself when we use it.
In custom-select.html
Now we have our ViewModel above defined, lets create the View. This is the easiest part of our custom element. All we are doing is wrapping a select element in the mandatory