Skip to content

On the sidelines, but still rooting for Angular

calendar_monthPosted on:November 11, 2025

For the last few months, I’ve been involved in several projects where I barely interact with or use Angular, if at all. There’s a reason why I worked hard to become a GDE, though: it’s still my framework of choice, and I want to keep spreading the word about how it continues to get better and effective ways to use it, so I always stay in the loop.

We’re already so close to the v21 release, so aside from hyping up the shiny new stuff that’s coming, let’s also take a few steps back and talk about my favorite features and changes from a few older versions.

Low key changes

Things like signals, zoneless, AI, and SSR are always in the limelight, but there are often tiny features and improvements that get shipped and go under the radar. Let’s cover some of them.

And now, the big ticket items.

Functional APIs

The shift to favoring functions over classes has been happening for years now, but we keep getting new goodies with every release. I discuss this at length in an article at the HeroDevs blog, in the context of some HTTP client changes, but in summary, functions are simpler to reason about, easier to make type-safe, and easier to compose. The framework benefits from said composition, making itself leaner when features are unused. inject is one of the best examples of this.

bootstrapApplication(App, {
  providers: [
    // Instead of raw DI tokens which are easy to mess up...
    {
      provide: APP_INITIALIZER,
      useValue: "this is not strongly typed",
      multi: true, // this flag is easily forgotten
    },
    // ...use strongly typed functions like this one
    provideAppInitializer(() => true),

    provideHttpClient(
      /* don't need JSONP? the framework doesn't 
         contain unnecessary code up front  */
      // withJsonpSupport(),

      withInterceptors([
        (req, next) => next(req), // inline functions
        configurableInterceptor(4), // this is harder to do with classes
      ])
    ),
  ],
});

Third-party libraries are doing this too, with the most prominent example being NgRx’s new Signals package. The benefits are clear, and we can only hope more and more APIs take advantage. Speaking of which…

Signals

Signals are the best thing to have happened to Angular in a long time. How can I express it all concisely? There’s enough to say about them to write 2 or more full articles!

In essence, they’re fine-grained reactive primitives tightly knit into the framework for reading and deriving state with precise change detection. (Which is why we can now go Zoneless!) They replace most component-local state and many RxJS patterns, lowering cognitive load while staying interoperable. Functional APIs (input, model, query signals) provide type-safe data flow, and render hooks like afterNextRender are client-only utilities for DOM work.

We could go on, including computed, linkedSignal, effect, resource, and more, but I’ll leave that to the excellent Signals guide in the official docs, or Cédric Exbrayat’s intro over at the Ninja Squad blog.

Angular Aria

Another big gap that has started getting filled was the need for a first-party headless UI library. Angular Material is great at what it does but comes with an opinionated design system that’s hard to modify (and sometimes just not meant to be). The CDK is a set of primitives, some of which are basically UI components, but most aren’t, and that’s not its primary goal anyway.

@angular/aria provides unstyled, thoughtfully built components with accessibility and performance in mind. It lives alongside CDK and Material and complements them well; you just bring your markup and styles, and Angular Aria gives you proper keyboard behavior, semantics, roles, and relationships so you don’t have to reinvent the wheel.

Angular Aria will launch in v21 including accordion, combobox, listbox, menu, radio-group, tabs, toolbar, tree, and more.

Signal forms

Saving the best for last: the new form APIs in Angular are here. Signal Forms are a ground-up redesign aimed at taking advantage of all the latest features, address long-standing complaints in the older patterns that were beyond fixing, and baking extensibility and composability in to prevent it from happening again.

Signal Forms are model driven, so by just providing a signal, you have a fully functional, HTML-compliant and compatible form.

readonly profile = signal({
  fullName: '',
  preferredName: '',
});

readonly profileForm = form(this.profile);
<form (submit)="save($event)">
  <label>Full Name <input [field]="profileForm.fullName" /></label>
  <label>Preferred Name <input [field]="profileForm.preferredName" /></label>
</form>

There’s so much to cover without its own content, so take a look at the official guide, but here are a few of my favorites:

Signal Forms are the future, and even though now it seems confusing to have a third way of creating forms, I expect this approach to supersede the others in the end. It’s just that good.


There’s never been a better time to bet on Angular, and it’s going to keep getting better. All barriers to adoption are dropping off one by one: whether it’s the cognitive barriers caused by RxJS and change detection, or the ecosystem integration challenges brought by Zone.js, Webpack, or TypeScript decorators, it’s all coming together, so what are you waiting for?