DEV Community

Cover image for Ng-News 25/14: Selectorless PR
ng-news for This is Angular

Posted on

2

Ng-News 25/14: Selectorless PR

Selectorless aims to eliminate the need for selectors in templates by referencing components directly via class names. A first PR has been merged, which shows the initial direction Angular is taking toward this feature.

Selectorless

Standalone components were introduced in Angular 14. They removed the abstraction of NgModules, which had caused some trouble for the compiler.
To figure out a component’s dependencies, the compiler first had to find the NgModule, which was usually in another file.

Modern bundlers are built for single-file compilation, which makes parallel builds possible. A perfect setup is if a file includes everything it needs, like its dependencies.

On the path towards single-file compilation, another obstacle, namely the selector, will be removed.

A component’s template uses selectors to reference its dependencies. The corresponding classes are imported in the TypeScript file, but that's not enough. Just having the name of the class doesn't tell anything about its selector.

So in order to find out the selector of that dependency, the compiler needs to access the classes' filename and therefore break single-file compilation.

An example:

import { ComponentA } from './component-a';
import { ComponentB } from './component-b';

@Component({
  template: '<app-home />',
  imports: [ComponentA, ComponentB]
})
class App {}
Enter fullscreen mode Exit fullscreen mode

The compiler needs to know what class is behind the selector app-home. With the information in this file, it is not possible to tell if it is ComponentA or CompomentB. So the compiler needs to traverse the imports to find the right class.

The fix is simple. Why use a selector at all? Just reference the class directly in the template. That's the same thing we've been doing in TypeScript all the time.

import { ComponentA } from './component-a';
import { ComponentB } from './component-b';

@Component({
  template: '<ComponentA />'
})
class App {}
Enter fullscreen mode Exit fullscreen mode

Additionally, if it is clear what class is used in the template, it is also more straightforward for the runtime, which leads to better performance.

And this is exactly what selectorless is all about.

Selectorless is in a very early stage. Eventually, we will get an RFC with much more details.

We first talked about selectorless at ng-conf 2024.

Originally, Angular was designed to enhance HTML elements with components and directives. That was deeply embedded in AngularJS because there was a global directive registry. Each directive has a selector that could match any element of the page as long as it satisfies the directive's selector. This means that the same HTML can behave very differently depending on the directives that match its elements.

In Angular, we had a hierarchical registry via NgModules. In each NgModule, you can declare components and directives, which can dynamically match elements in the templates of components that belong to the transitive closure of these NgModules. This way, if you provide the same component in the context of a different trasitive closure, the elements of its template can match different components and directives and have a completely different behavior.

Throughout the years, we saw that NgModules was a redundant concept, creating a lot of indirection, confusion, and complexity. That's why we developed "standalone components" in v14. With standalone components, you have an imports array in the metadata to import the directives and components you use in your template.

See how with standalone components, we're removing the indirection. The component's template can match only the directives and components that are within its import array. What we're left with is a static enhancement of the HTML and redundant "double import"—you import the components and directives once in the TypeScript file and once in the component metadata.

Instead of having this duplication of imports and unnecessary indirection, selectorless enable us to import directives and components and directly use them in a template.

That's only a fraction of the benefit, though! In TypeScript, we have a dependency graph that comes from the module imports. Component and directive selectors create yet another dependency graph that the TypeScript compiler is not aware of. This requires us to figure out the dependencies of the components with the Angular compiler and prevents us from performing efficient single-file compilation (i.e., we're losing locality).

Selectorless enables locality and single-file compilation.

Additionally, selector matching happens at runtime and requires extra code. With selectorless, we can remove the overhead of selector matching and get an even faster and smaller runtime.

In summary, selectorless reduces boilerplate, makes compilation faster with locality, shrinks the runtime, and makes it faster.

Selectorless template parsing #60724

⚠️ Disclaimer ⚠️ this PR implements syntax that is still being designed and discussed. It's an initial prototype that will allow us experiment with the runtime and run user studies.

These changes are an initial implementation of the template parsing for selectorless templates. Here's an example showing most of the syntax where we create a MatButton component as a link, we apply the HasRipple directive without any inputs and set a tooltip that's only enabled if the user doesn't have permissions to go to the admin page:

<MatButton:a href="/admin" @HasRipple @Tooltip(message="Cannot navigate" [disabled]="hasPermissions")>Admin</MatButton:a>
Enter fullscreen mode Exit fullscreen mode

#angular #typescript #programming #webdev #webdevelopment #javascript | Minko Gechev | 80 comments

So excited to see selectorless taking shape! In summary: selectorless removes the boilerplate in standalone components (&quot;double import&quot;), opens the door for many build time optimizations thanks to locality, and makes the framework smaller and faster. Here&#39;s an in-depth explanation https://lnkd.in/gNFWjdt4 This snippet shows the *entire* syntax of selectorless. Most components will look like this: &lt;MyButton [label]&#61;&quot;expression&quot;/&gt; instead of &lt;button my-button [label]&#61;&quot;expression&quot;/&gt; You can find the early syntax we&#39;re thinking about below. We&#39;ll share an RFC to collect community feedback in the upcoming months. And here&#39;s the template parsing pull request 👉https://lnkd.in/gask3_SK #angular #typescript #programming #webdev #webdevelopment #javascript | 80 comments on LinkedIn

favicon linkedin.com

Q&A Session

At the monthly Q&A session, Jeremy Elbourn briefly touched on the router in the context of making RxJS optional in Angular.

He mentioned that there won’t be a full rewrite of the router, but that the current router state might be exposed as a Signal in the future.
Time Position: 1:18:40

Zoneless in Developer Preview?

A PR landed, which will make zoneless leaving its experimental status, which it had since Angular 18. Chances are high, that this PR makes it into Angular 20.

feat(core): Move zoneless change detection to dev preview #60748

This commit moves zoneless from experimental to developer preview.

  • Update tag on provider API
  • Remove "experimental" from provider name
  • Move documentation from "experimental features" to "Best practices -> Performance" (at least temporarily until there is a better place)

Blocked by the following:

Follow up work:

Nx Remote Caching

Nx, an alternative to the Angular CLI, provides an option for a centralized build cache. That means, once a build is available, it is cached, and if the underlying code didn't change at all, subsequent builds can be served by the cache.

There have been some discussions about closing the API which allows writing the build cache on your own. That is now off the table. We will get a new API where we can write our self-hosted caches for free.

Nx - Remote Cache

Free remote caching solutions for any team. Pick from Managed Remote Cache with Nx Cloud, Self-Hosted Cache Plugins, or Build Your Own with our OpenAPI specs.

favicon nx.dev

httpResource at Angular Catch-Up

Alex Rickabaugh was guest at the Angular Catch-Up podcast and talked about the new function httpResource.

Alex mentioned that resource is not already "state management" but an API for the existing state management libraries and they should use it to implement their approach to that problem.

He also mentioned that we have to remember that httpResource is eagerly loaded and not lazily like Observables.

https://www.podbean.com/ew/pb-4th8u-186896c

Fakes over Mocks

Last but not least, there has also been an article by Younes Jaaidi about testing. He suggests to lean more towards fakes instead of mocks for test doubles and illustrated his argument with some quite eye-opening examples.

https://cookbook.marmicode.io/angular/fake-it-till-you-mock-it

ng-de Dates

The German Angular conference, ng-de, has announced its dates. It is going to be on November 5th to 7th and the CFP has also opened.

NG-DE Berlin 2025 | The First Community-Driven Angular Conference in Germany

Join Germany's largest Angular conference! November 5-7, 2025 in Berlin featuring workshops, talks, and networking.

favicon ng-de.org

Top comments (0)