Table of Contents
Key Takeaways
Why the Need for More Markup?
Enhancing Existing Elements with Custom Attributes
Creating the popover
Create New Tags with Custom Elements
Reducing the Amount of Code with Conventions
Conclusion
Frequently Asked Questions (FAQs) about Extending HTML with Aurelia.io
What is Aurelia.io and how does it extend HTML?
How does Aurelia.io compare to other JavaScript frameworks?
How do I create custom elements in Aurelia.io?
What are custom attributes in Aurelia.io and how do I use them?
How does Aurelia.io handle data binding?
Can I use Aurelia.io with other JavaScript libraries and frameworks?
How does Aurelia.io handle routing and navigation?
What is the learning curve for Aurelia.io?
How is Aurelia.io tested and what is its performance like?
What kind of support and community does Aurelia.io have?
Home Web Front-end JS Tutorial Extending HTML the Aurelia.io Way

Extending HTML the Aurelia.io Way

Feb 20, 2025 am 11:05 AM

Extending HTML the Aurelia.io Way

Key Takeaways

  • Aurelia.io, a modern JavaScript framework, allows developers to create custom elements and attributes in HTML, enhancing the flexibility and functionality of web applications.
  • Custom attributes in Aurelia.io can be used to wrap existing plugins, provide shortcuts for common bindings, or alter existing HTML elements without direct code access. This makes it easier to add new features to existing elements.
  • Creating new elements in Aurelia.io involves defining a class for the element and a view for its HTML representation. This enables the creation of entirely new elements with custom behavior and structure, improving code reuse and modular design.
  • Aurelia.io uses a set of simple conventions to reduce the amount of code required, making it more developer-friendly. It also offers compatibility with other JavaScript libraries and frameworks, allowing for greater flexibility in web development.

Teaching the old dog HTML new tricks is a major focus of today’s modern JavaScript frameworks. Be it by following potential standards like WebComponents, creating custom Directives or by extending existing classes, chances are high that your framework of choice provides a means to extend HTML’s markup itself. In a previous article, written by Brad Barrow, you were introduced to a new player: Aurelia. This article will build upon Brad’s article and code and show you how to create custom elements as well as custom attributes by following Aurelia’s conventions.

The complete code for this article can be found on our GitHub repo and you can see a demo of what we are going to build here (please allow some time for the app to initialize).

Why the Need for More Markup?

Before jumping straight into the action let’s first understand the potential use case for creating new components. To do so we will take a conceptual look at the introductory example as shown in the figure below. We have two pages, represented by a ViewModel (VM) and a View, showing funny pictures and gif videos. Each of those has a repeated list which itself renders posts containing an image and a text block.

Extending HTML the Aurelia.io Way

Aurelia Reddit Client conceptual diagram

By looking at the View we can see that data acquisition, as well as rendering, is tightly coupled in one VM/View pair.

<span><span><span><template</span>></span>
</span>  <span><span><span><ul</span> class<span>="list-group"</span>></span>
</span>    <span><span><span><li</span> class<span>="list-group-item"</span> repeat.for<span>="p of posts"</span>></span>
</span>      <span><span><span><img</span> src.bind<span>="p.data.thumbnail"</span> /></span>
</span>      <span><span><span><a</span> href<span>="http://reddit.com${p.data.permalink}"</span>></span>
</span>        ${p.data.title}
      <span><span><span></a</span>></span>
</span>    <span><span><span></li</span>></span>
</span>  <span><span><span></ul</span>></span>
</span><span><span><span></template</span>></span></span>
Copy after login
Copy after login
Copy after login
Copy after login

This might not be a problem with a simple example, but can turn into a major drawback as the system grows and more and more requirements are gathered.

Enhancing Existing Elements with Custom Attributes

Imagine we get a request to provide a popover for each of the funny pages posts. In order to do that we could easily wire up Bootstrap’s feature directly into the markup by placing the necessary data- attributes followed by an initialization inside our FunnyVM. But what if we suddenly need to do it on the other page as well? Providing the feature by declaring a custom attribute can make our lives much easier. These are particularly useful in following scenarios:

  • Wrapping existing plugins
  • Shortcuts for common bindings such as style or class
  • Altering existing HTML elements / custom elements without direct code access

Now let’s get our hands dirty and see what it takes to build our first custom attribute.

Creating the popover

Let’s start by looking at what we’d like to achieve. The new attribute popover should accept parameters for the placement, title and content of the popover. The placement is fixed to the right, so a simple string as value is enough. For the other two properties we’re going to use Aurelia’s data binding to map the iterated values. In order to load the file we make use of Aurelia’s require feature. The from attribute contains the relative path to the resource to be imported.

<span><span><span><template</span>></span>
</span>  <span><span><span><ul</span> class<span>="list-group"</span>></span>
</span>    <span><span><span><li</span> class<span>="list-group-item"</span> repeat.for<span>="p of posts"</span>></span>
</span>      <span><span><span><img</span> src.bind<span>="p.data.thumbnail"</span> /></span>
</span>      <span><span><span><a</span> href<span>="http://reddit.com${p.data.permalink}"</span>></span>
</span>        ${p.data.title}
      <span><span><span></a</span>></span>
</span>    <span><span><span></li</span>></span>
</span>  <span><span><span></ul</span>></span>
</span><span><span><span></template</span>></span></span>
Copy after login
Copy after login
Copy after login
Copy after login

In order to make that happen, we start by creating a new JavaScript file in the src folder called popover.js. The custom attribute, like all other Aurelia constructs, is a simple exported ES6 class rather than a collection of functions passed into a predefined API (as many legacy frameworks do).

<span><span><span><require</span> from<span>="./popover"</span>></span><span><span></require</span>></span>    
</span>...
<span><span><span><img</span> src.bind<span>="p.data.thumbnail"</span>
</span></span><span>     <span>popover<span>="placement: 'right';
</span></span></span><span><span>              title.bind: p.data.url;
</span></span><span><span>              content.bind: p.data.title<span>"</span> /></span></span>
Copy after login
Copy after login
Copy after login

Compared to other frameworks, Aurelia declares constructs by describing them via metadata. But instead of using static functions or complicated APIs, Aurelia leverages cutting edge ES7 Decorators to achieve that. We’re going to import the necessary decorators from the package aurelia-framework. As for the control itself, we will use the Popover JavaScript control provided by Twitter Bootstrap. So we import the jQuery handle $ as well as bootstrap in order to initialize Bootstraps’ JavaScript code.

The next step is to apply the previously mentioned metadata so that Aurelia knows what it gets when it loads the file. By attaching the customAttribute decorator we name our component with the given value. The bindable decorator on the other hand is declaring a property which our View can bind to. We simply repeat this decorator for each available property.

<span>import <span>{customAttribute, bindable, inject}</span> from 'aurelia-framework';
</span><span>import $ from 'bootstrap';
</span><span>import bootstrap from 'bootstrap';
</span><span>...</span>
Copy after login
Copy after login

The first inject decorator takes care of providing the actual DOM element as a parameter to our constructor method, which is then stored for later use.

<span><span><span><template</span>></span>
</span>  <span><span><span><ul</span> class<span>="list-group"</span>></span>
</span>    <span><span><span><li</span> class<span>="list-group-item"</span> repeat.for<span>="p of posts"</span>></span>
</span>      <span><span><span><img</span> src.bind<span>="p.data.thumbnail"</span> /></span>
</span>      <span><span><span><a</span> href<span>="http://reddit.com${p.data.permalink}"</span>></span>
</span>        ${p.data.title}
      <span><span><span></a</span>></span>
</span>    <span><span><span></li</span>></span>
</span>  <span><span><span></ul</span>></span>
</span><span><span><span></template</span>></span></span>
Copy after login
Copy after login
Copy after login
Copy after login

Now that we have all the necessary information we can opt into the Behaviors life cycle by declaring a method called bind. This makes sure we initialize the component at the proper timing, comparable to jQuery’s ready method.

<span><span><span><require</span> from<span>="./popover"</span>></span><span><span></require</span>></span>    
</span>...
<span><span><span><img</span> src.bind<span>="p.data.thumbnail"</span>
</span></span><span>     <span>popover<span>="placement: 'right';
</span></span></span><span><span>              title.bind: p.data.url;
</span></span><span><span>              content.bind: p.data.title<span>"</span> /></span></span>
Copy after login
Copy after login
Copy after login

Last but not least, we add the changed handlers. Note that these aren’t actually executed in our example, since the binding source is not changing over time.

<span>import <span>{customAttribute, bindable, inject}</span> from 'aurelia-framework';
</span><span>import $ from 'bootstrap';
</span><span>import bootstrap from 'bootstrap';
</span><span>...</span>
Copy after login
Copy after login

View the complete file on GitHub

Now that we’ve seen how you can add new features by providing attributes to existing elements, let’s move on and start writing our own custom elements.

Create New Tags with Custom Elements

In order to create entirely new elements, Aurelia leverages a very similar approach to custom attributes. As an example we’re going to re-build the gif page’s posts to be represented by a custom element called reddit-gif and provide the possibility to toggle the actual video on and off. The resulting markup for our View should be this:

@<span>inject(Element)
</span>@<span>customAttribute('popover')
</span>@<span>bindable('title')
</span>@<span>bindable('content')
</span>@<span>bindable('placement')
</span><span>export class Popover {
</span><span>...</span>
Copy after login

As you can see we use the new tag and provide necessary information via data bindings to the data property.

The next step is to create the actual element. We do that by creating the element’s view reddit-gif.html and its VM reddit-gif.js in the folder src. The view, seen next, is leveraging the previous markup from gifs.html and adding a button which toggles an iframe that is used to embed the actual video. Again, Aurelia’s views are wrapped inside a template tag:

<span>constructor(element) {
</span>  <span>this.element = element;
</span><span>}</span>
Copy after login

Looking at the VM part, we do follow a similar process as when creating a custom attribute. But this time we leverage a different decorator which will tell Aurelia that we’re going to create a customElement with only one property named data.

<span>bind() {
</span>  <span>// initialize the popover
</span>  <span>$(this.element).popover({ 
</span>    <span>title: this.title,
</span>    <span>placement: this.placement,
</span>    <span>content: this.content,
</span>    <span>trigger: 'hover' });
</span><span>}</span>
Copy after login

Next we are defining a gifActive member to keep track of whether the iframe should be displayed. We also initially set the gifSrc member to empty, in order to not pre-load any contents if the iframe is invisible.

<span>titleChanged(newValue){
</span>  <span>$(this.element).data('bs.popover').options.title = newValue;
</span><span>}
</span>
<span>contentChanged(newValue){
</span>  <span>$(this.element).data('bs.popover').options.content = newValue;
</span><span>}
</span>
<span>placementChanged(newValue){
</span>  <span>$(this.element).data('bs.popover').options.placement = newValue;
</span><span>}</span>
Copy after login

Last but not least, we add the toggleGif function used by the toggle button which flips the visibility and source on each call.

<span><span><span><require</span> from<span>="./reddit-gif"</span>></span><span><span></require</span>></span>
</span>...
<span><span><span><ul</span> class<span>="list-group"</span>></span>
</span>    <span><span><span><li</span> class<span>="list-group-item"</span> repeat.for<span>="p of posts"</span>></span>
</span>      <span><span><span><reddit-gif</span> data.bind<span>="p.data"</span>></span><span><span></reddit-gif</span>></span>
</span>    <span><span><span></li</span>></span>
</span><span><span><span></ul</span>></span></span>
Copy after login

You can view the complete HTML file here and the JS file here

Reducing the Amount of Code with Conventions

Aurelia is all about making the developer experience as pleasant as possible. Let’s face the truth: many of us don’t like to type a lot. So, in order to save you some valuable keystrokes and improve maintenance over time, Aurelia uses a set of simple conventions. For example, the full version of a bindable decorator actually might look like this, which we worked around by just providing the property name. All other options will be automatically inferred.

<span><span><span><template</span>></span>
</span>  <span><span><span><ul</span> class<span>="list-group"</span>></span>
</span>    <span><span><span><li</span> class<span>="list-group-item"</span> repeat.for<span>="p of posts"</span>></span>
</span>      <span><span><span><img</span> src.bind<span>="p.data.thumbnail"</span> /></span>
</span>      <span><span><span><a</span> href<span>="http://reddit.com${p.data.permalink}"</span>></span>
</span>        ${p.data.title}
      <span><span><span></a</span>></span>
</span>    <span><span><span></li</span>></span>
</span>  <span><span><span></ul</span>></span>
</span><span><span><span></template</span>></span></span>
Copy after login
Copy after login
Copy after login
Copy after login

Another thing to look at is how to shorten up usage of multiple properties. So instead of defining each of them one by one, we can also tell our custom attribute to expect dynamic properties. To do so we decorate our class with the dynamicOptions decorator. Now we can still reuse the same view markup but don’t have to manually define all property declarations which, as the name suggests, is quite helpful in dynamic contexts. This means we can write one general changed-handler called dynamicPropertyChanged, which gets called whenever any bound property gets changed.

<span><span><span><require</span> from<span>="./popover"</span>></span><span><span></require</span>></span>    
</span>...
<span><span><span><img</span> src.bind<span>="p.data.thumbnail"</span>
</span></span><span>     <span>popover<span>="placement: 'right';
</span></span></span><span><span>              title.bind: p.data.url;
</span></span><span><span>              content.bind: p.data.title<span>"</span> /></span></span>
Copy after login
Copy after login
Copy after login

But what about custom elements? Well we’ve implicitly used some conventions already without even realizing it. The system automatically pulled together the View and VM pair just by them having the same name. If you need to use a different view though you may use the decorator @useView(relativePath). Or maybe not use a view at all by declaring @noView. We can even go crazy and let our view be rendered in the ShadowDOM by adding the decorator useShadowDOM. If you are unfamiliar with that term, please take a look at this article

Conclusion

We, the Aurelia Team, hope to have given you a quick overview of how to extend HTML itself by leveraging custom elements and attributes. Throughout the examples we hope that you’ve been able to see our focus on developer experience by offering you a flexible, yet easy to use framework, which doesn’t stand in your way or make you use a strange API. We’d like to invite you to join our Gitter channel if you have any questions. We would also love to hear of your experiences as you write your first custom elements and attributes.

Frequently Asked Questions (FAQs) about Extending HTML with Aurelia.io

What is Aurelia.io and how does it extend HTML?

Aurelia.io is a modern, open-source JavaScript framework for web, mobile, and desktop development. It extends HTML by allowing developers to create custom HTML elements, add custom attributes to existing HTML elements, and control the flow of HTML rendering. This is achieved through Aurelia’s powerful templating engine, which interprets custom elements and attributes and renders them as standard HTML. This allows for more dynamic, interactive, and complex web applications while maintaining clean, readable code.

How does Aurelia.io compare to other JavaScript frameworks?

Aurelia.io stands out from other JavaScript frameworks due to its focus on web standards, simplicity, and extensibility. Unlike many frameworks, Aurelia.io is designed to be a collection of collaborating libraries, which means you can use as much or as little of the framework as you need. It also emphasizes clean, convention-based coding, reducing the amount of boilerplate code needed. Furthermore, Aurelia.io’s commitment to following web standards means that your code will be future-proof and compatible with upcoming web technologies.

How do I create custom elements in Aurelia.io?

Creating custom elements in Aurelia.io involves defining a class for the element and a view for its HTML representation. The class contains the logic for the element, while the view defines its HTML structure. Once defined, the custom element can be used in any Aurelia.io application just like a standard HTML element. This allows for code reuse and modular design, making your applications easier to develop and maintain.

What are custom attributes in Aurelia.io and how do I use them?

Custom attributes in Aurelia.io are a way to add custom behavior to existing HTML elements. They are defined in a similar way to custom elements, with a class for the attribute’s logic and a view for its HTML representation. Once defined, the custom attribute can be added to any HTML element in an Aurelia.io application, extending its functionality without needing to create a whole new element.

How does Aurelia.io handle data binding?

Aurelia.io supports two-way data binding, meaning changes in the model automatically update the view, and vice versa. This is achieved through Aurelia.io’s observability system, which tracks changes to data and updates the relevant parts of the view. This makes it easy to create dynamic, interactive applications where the UI always reflects the current state of the data.

Can I use Aurelia.io with other JavaScript libraries and frameworks?

Yes, Aurelia.io is designed to be compatible with other JavaScript libraries and frameworks. It uses a modular architecture, meaning you can pick and choose which parts of the framework to use. This makes it easy to integrate Aurelia.io into existing projects, or to use other libraries and frameworks alongside Aurelia.io.

How does Aurelia.io handle routing and navigation?

Aurelia.io includes a powerful router that allows for complex navigation scenarios. The router supports nested routes, optional parameters, and dynamic routes, among other features. This makes it easy to create single-page applications with Aurelia.io, where the user can navigate between different views without refreshing the page.

What is the learning curve for Aurelia.io?

Aurelia.io is designed to be easy to learn, with a focus on simplicity and convention over configuration. If you’re familiar with JavaScript and HTML, you should be able to pick up Aurelia.io quickly. The framework’s documentation is comprehensive and includes plenty of examples to help you get started.

How is Aurelia.io tested and what is its performance like?

Aurelia.io is thoroughly tested to ensure its reliability and performance. It uses a combination of unit tests, integration tests, and end-to-end tests to cover all aspects of the framework. In terms of performance, Aurelia.io is designed to be fast and efficient, with a minimal footprint and optimized rendering.

What kind of support and community does Aurelia.io have?

Aurelia.io has a vibrant and active community of developers who contribute to the framework and provide support to each other. There are numerous resources available, including a community forum, a Gitter chat room, and a Stack Overflow tag. In addition, the Aurelia.io team provides professional support and training services.

The above is the detailed content of Extending HTML the Aurelia.io Way. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1653
14
PHP Tutorial
1251
29
C# Tutorial
1224
24
What should I do if I encounter garbled code printing for front-end thermal paper receipts? What should I do if I encounter garbled code printing for front-end thermal paper receipts? Apr 04, 2025 pm 02:42 PM

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

Demystifying JavaScript: What It Does and Why It Matters Demystifying JavaScript: What It Does and Why It Matters Apr 09, 2025 am 12:07 AM

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

Who gets paid more Python or JavaScript? Who gets paid more Python or JavaScript? Apr 04, 2025 am 12:09 AM

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

How to achieve parallax scrolling and element animation effects, like Shiseido's official website?
or:
How can we achieve the animation effect accompanied by page scrolling like Shiseido's official website? How to achieve parallax scrolling and element animation effects, like Shiseido's official website? or: How can we achieve the animation effect accompanied by page scrolling like Shiseido's official website? Apr 04, 2025 pm 05:36 PM

Discussion on the realization of parallax scrolling and element animation effects in this article will explore how to achieve similar to Shiseido official website (https://www.shiseido.co.jp/sb/wonderland/)...

Is JavaScript hard to learn? Is JavaScript hard to learn? Apr 03, 2025 am 12:20 AM

Learning JavaScript is not difficult, but it is challenging. 1) Understand basic concepts such as variables, data types, functions, etc. 2) Master asynchronous programming and implement it through event loops. 3) Use DOM operations and Promise to handle asynchronous requests. 4) Avoid common mistakes and use debugging techniques. 5) Optimize performance and follow best practices.

The Evolution of JavaScript: Current Trends and Future Prospects The Evolution of JavaScript: Current Trends and Future Prospects Apr 10, 2025 am 09:33 AM

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

How to merge array elements with the same ID into one object using JavaScript? How to merge array elements with the same ID into one object using JavaScript? Apr 04, 2025 pm 05:09 PM

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

How to implement panel drag and drop adjustment function similar to VSCode in front-end development? How to implement panel drag and drop adjustment function similar to VSCode in front-end development? Apr 04, 2025 pm 02:06 PM

Explore the implementation of panel drag and drop adjustment function similar to VSCode in the front-end. In front-end development, how to implement VSCode similar to VSCode...

See all articles