Why the revised Angular style guide matters

Back in 2016, Angular 2.0.0 shipped alongside a detailed 52-page coding style guide. Eight years and 16 major releases later, the framework has changed considerably. To bring the guidance up to date, Jeremy Elbourn, Angular’s technical lead at Google, has started a major overhaul of the official style guide.

Draft of the new Angular coding style guide.

What the Angular team wants to achieve

In this RFC on the Angular GitHub repo, Jeremy lays out the team’s objectives for the new guide:

  • Focus on style rather than general engineering best practices.
  • Update the content to cover newer features and APIs.
  • Revise recommendations based on lessons from real-world usage.
  • Shrink the guide to around 4 pages, a major reduction from 52.
  • Point elsewhere for non-Angular advice, specifically to Google's TS style guide.

It's a draft — so why pay attention now?

Even though the document is still in draft form and an official release may be a ways off (v20.0.0 would be a natural fit, following v2.0.0), there's a strong case for adopting its suggestions right away.

In my view, the core ideas in the draft are both sound and practical. Below, I’ll walk through the parts I find most valuable.

Overall impressions

In the opening section, Jeremy states:

When in doubt, prefer consistency

That resonates with me completely. Even though these aren’t formal style-guide rules, they’re the three principles I consistently emphasize in Angular essential and other workshops:

  • Keep it short & simple (write less code, cap files at roughly 400 lines, prefer small functions, etc.)
  • Don't repeat yourself (extract helpers, services, pipes, and other reusable pieces)
  • Be consistent (use Prettier, follow style guides, and stick with your choices)

Small is beautiful (my own addition)

Although the 400-line limit is being dropped from the new "Angular-specific" guidance, I still think it’s a worthwhile target. Across the many Angular codebases I’ve worked with, components frequently blow past this number, and that’s usually where maintainability starts to suffer. Keeping components reasonably compact can make a real difference in how easily developers can maintain them over time. There are several ways to reduce component complexity; here are three that matter most to me:

  • Build smaller Angular pieces, such as subcomponents, directives, services, and pipes
  • Use state management or component-level state facades (implemented as services)
  • Move helper logic into separate files or classes

Jeremy also calls out changes to file naming rules and project layout recommendations. These updates are meant to improve consistency and make it easier for developers to find their way around an Angular codebase.

Naming of files

Yes, the file naming conventions are going to change — but I’ll hold off on details, since they may still be tweaked. My guess is that a migration script will handle the renaming, so the switch shouldn’t be painful.

Project structure

A notable suggestion in the structure guidance is to organize features into dedicated folders. This matches the approach our Angular Architects Team takes when structuring enterprise Angular applications:

  • Use an Nrwl Nx monorepo with libraries to separate features, or
  • Use a lightweight tool like Sheriff to enforce feature boundaries.

In both setups, we recommend (though it’s not mandatory) applying domain-driven design (DDD) to determine where those boundaries should lie. Manfred covers this in more depth in his article on Strategic Design with Sheriff and Standalone Components.

Another guideline I’m fond of: One concept per file. When each file sticks to a single concept — be it an Angular building block or a set of types — the codebase stays clearer and simpler to reason about.

Standout items in the new style guide

Below are a few personal favorites from the draft, along with some small additions and observations:

Keep components focused on presentation

Don’t bury complex business logic inside components. Move that logic into your store or services. If a template starts getting unwieldy, shift the logic back into the TypeScript code so it’s easier to read and maintain.

Group Angular-specific properties before methods

This ordering puts inputs, outputs, and queries first, followed by other properties and then methods. For my part, I also like to place all injected dependencies at the bottom, sorted alphabetically, and always before the first method. As Jeremy puts it, “This practice makes it easier to find the class’s template APIs and dependencies.”

Keep (constructor and) lifecycle methods simple

Resist the urge to put heavy or elaborate logic in the constructor or lifecycle hooks such as ngOnInit. Instead, extract that logic into clearly named methods and invoke them from the hook. This makes components easier to scan and understand.

ngOnInit(): void { // <-- don't forget to add the return type on all your methods ;-)
  this.startLogging();
  this.runBackgroundTask(); // <-- not sure if this is the best possible method name ;-)
}

Use protected on component class members used in the template

Limiting visibility through access modifiers is a solid habit for cleaner code. When I come across fields without any modifier, it feels unfinished.

A month back, after polling the Angular Architects Team, we agreed that marking template-bound fields as protected is a good call. It’s nice to see that recommendation land in the official guide! One small caveat: if a field isn’t used in the template, the natural default is private.

Quick note: I strongly advise against explicitly writing the public keyword, since it’s already the default and adds no value. In Angular building blocks, making members public (by leaving the modifier off 😏) should be the exception, not the rule.

@Component({
  /* ... */
  template: `<p>{{ fullName() }}</p>`,
})
export class UserProfile {
  readonly firstName = input();
  readonly lastName = input();

  // `fullName` is not part of the component's API, but is used in the template
  protected readonly fullName = computed(() => `${this.firstName()} ${this.lastName()}`);
}

Use readonly on properties initialized by Angular (and more)

Over a year ago, I started marking nearly everything as readonly — the same instinct that leads me to prefer const over let. That includes signals, injected dependencies, @Output fields, and query APIs. I skip it for @Input properties, though, since readonly doesn't work there. It takes a bit of extra effort, but I find the added clarity makes it worthwhile.

@Component({
  /* ... */
})
export class UserProfile {
  readonly userId = input();
  readonly userSaved = output();

  private readonly userService = inject(UserService);
}

Prefer class and style over ngClass and ngStyle

This is something I’ve taught in workshops for years. It makes templates more readable and works nicely with tools like Prettier.

<div [class.admin]="isAdmin" [class.dense]="density === 'high'"></div>

Name event handlers for what they do, not for the triggering event

I’ve only recently started following this convention, and it makes a difference — you can tell what an event does just by reading the template. In general, clear and descriptive names for symbols and methods are essential for maintainability.

<button (click)="saveUserData()">Save</button>

That's all folks

I hope this selection proves useful! If you think I missed a key rule, or you believe Jeremy cut too much from the original guide, feel free to reach out via email or join one of the upcoming workshops. The revised style guide will be woven into all my examples — both demos and exercises — and will take center stage in the best practices workshop:

Workshops

If you want to dive deeper into Angular, we offer workshops in both English and German.

If quality is your focus, don’t miss the:

This blog post was written by Alexander Thalhammer. Follow me on Linkedin, X or giThub.