Custom attributes
Using built-in custom attributes and building your own.
A custom attribute allows you to create special properties to enhance and decorate existing HTML elements and components. Natively attributes exist in the form of things such as disabled
on form inputs or aria text labels. Where custom attributes can be especially useful is wrapping existing HTML plugins that generate their own markup.
Creating custom attributes
On a simplistic level, custom attributes resemble components quite a lot. They can have bindable properties, and they use classes for their definitions.
A basic custom attribute looks something like this:
If you were to replace CustomAttribute
with CustomElement
, it would be a component. On a core level, custom attributes are a more primitive component form.
Let's create a custom attribute that adds a red background and height to any dom element it is used on:
Now, let's use our custom attribute:
We import our custom attribute so the DI knows about it and then use it on an empty DIV. We'll have a red background element with a height of one hundred pixels.
Explicit custom attributes
The customAttribute
decorator allows you to create custom attributes, including the name explicitly. Other configuration options include the ability to create aliases.
Explicit attribute naming
You can explicitly name the custom attribute using the name
configuration property.
Attribute aliases
The customAttribute
allows you to create one or more aliases that this attribute can go by.
We can now use our custom attribute using the registered name red-square
as well as redify
and redbox
the following example highlights using both aliases on an element.
Single value binding
Sometimes, you want a custom attribute with only one bindable property. You don't need to define the bindable property explicitly to do this, as Aurelia supports custom attributes with single-value bindings.
The value
property is automatically populated if a value is supplied to a custom attribute, however, requires you to define the value property as a bindable explicitly.
When the value is changed, we can access it like this:
Accessing the element
When using the custom attribute on a dom element, there are instances where you want to be able to access the element itself. To do this, you can use the INode
decorator and HTMLElement
interface to inject and target the element.
The code above was lifted from the first example, allowing us to access the element itself on the class using this.element
This is how we can set CSS values and perform other modifications, such as initialising third-party libraries like jQuery and other libraries.
You can also use resolve(Element)
or resolve(HTMLElement)
to get the host element, just like INode
. However, using INode
makes it safer when used in Nodejs environment since there will not be a global Element
or HTMLElement
. If you are not planning to run your application in Nodejs environment, you can also just use Element
or HTMLElement
, like this: resolve(Element)
or resolve(HTMLElement)
.
Custom attributes with bindable properties
In many cases, you might only need custom attributes without user-configurable properties. However, in some cases, you want the user to be able to pass in one or more properties to change the behavior of the custom attribute (like a plugin).
Using bindable properties, you can create a configurable custom attribute. Taking our example from above, let's make the background color configurable instead of always red. We will rename the attribute for this.
We can now provide a color on a per-use basis. Let's go one step further and allow the size to be set too.
Responding to bindable property change events
We have code that will work on the first initialization of our custom property, but if the property is changed after rendering, nothing else will happen. We need to use the change detection functionality to update the element when any bindable properties change.
As a default convention, bindable property change callbacks will use the bindable property name followed by a suffix of Changed
at the end. The change callback gets two parameters, the new value and the existing value.
Want to learn more about bindable properties and how to configure them? Please reference the bindable properties section.
Whenever our size or color bindable properties change, our element will be updated accordingly instead of only at render.
Options binding
Options binding provides a custom attribute with the ability to have multiple bindable properties. Each bindable property must be specified using the bindable
decorator. The attribute view model may implement an optional ${propertyName}Changed(newValue, oldValue)
callback function for each bindable property.
When binding to these options, separate each option with a semicolon and supply a binding command or literal value, as in the example below. It is important to note that bindable properties are converted to dash-case when used in the DOM, while the view model property they are bound to is kept with their original casing.
To use options binding, here is how you might configure those properties:
Specifying a primary property
When you have more than one bindable property, you might want to specify which property is the primary one (if any). If you mostly expect the user only to configure one property most of the time, you can specify it is the primary property through the bindable configuration.
The above example specifies that color is the primary bindable property. Our code actually doesn't change at all. The way we consume the custom attribute changes slightly.
Or, you can bind the value itself to the attribute:
Finding a custom attribute from the DOM
Sometimes, custom attributes are developed in a group of 2 or more, e.g attributes for a dropdown + toggle button inside it, and it's necessary to retrieve the "parent" attribute from a child attribute. One way to do this is to use CustomAttribute.closest
function for walking the DOM and finding a particular custom attribute, based on either name, or the constructor. The name closest
mimics the DOM API Element.prototype.closest
.
An example of the CustomAttribute.closest
is as follow:
Or the following also works if you want to search using the constructor:
Last updated