When to use an attribute selector for Angular components

Wojciech Trawiński
JavaScript everyday
3 min readMar 31, 2020

A CSS element selector is by far the most popular way to mark an Angular component. Although, an attribute selector is mainly meant to be used for Angular directives, you can use it as a component selector as well. In this blog post I’ll present two scenarios when such an approach seems to be the most appropriate 👌.

Table row

Let’s assume that you have a simple table in your project which contains car data:

The markup for the above table is quite simple:

At some point, you realize that it would be a good idea to extract the row markup into a separate component:

and use it in the following way:

Unfortunately, the result is far from what you probably expect 😿:

The above behavior stems from the fact that some DOM elements cannot have any additional nodes between them, namely a tr element has to be a child of a tbody element. The presence of the Angular component (marked with an element selector) between them is forbidden 🚫:

However, you can use an HTML attribute for the row component selector in order to preserve the required DOM nodes hierarchy:

and use it in the following way:

Now, everything works as expected, since no additional element is located between the table nodes, and the row’s markup is extracted into a separate component 🎆:

Custom button

If you create a custom component which wraps a native one, you may end up with the following solution:

with a simple markup:

At first sight, it looks great and you may wonder why I encourage you to try a different solution. The biggest drawback of the above approach is that you loose a direct access to the native button API 😱. As a result, you need to proxy the disabled property by creating an input property. The presented solution is obviously against Open-Closed principle, since every new requirement to interact with the native button API will result in a change inside the component — adding input/output property.

If you use an attribute selector for your custom button component, you have a direct access to the native button element. Moreover, all the additional features which you implemented in the previous example are preserved 😸:

You can use the component in the following way:

Conclusions

The usage of attribute selectors is not limited to directives only, since you can use them as selectors for Angular components as well. Sometimes it’s the only possibility as with the table row example, whereas it’s an option for scenarios such as presented in the second case. However, bear in mind that Angular Material follows the same approach when it comes to buttons and even official Angular docs recommends such solution, see here.

Feel free to play around with the example:

I hope you liked the post and learned something new 👍 If so, please give me some applause 👏

--

--