Skip to content

Angular Style Guide

Contents:

Order of Imports in an Angular Module

For readability and consistency, imports in an Angular module should be ordered as follows:

  • Angular SDK imports
  • Steel Ridge Partner imports
  • Legacy Module imports (ordered alphabetically)
  • Standard Module imports
  • .. the rest

Order of Properties / Methods in a Component or Service

In general, components / services should have the following general order, as applicable for the specific use case:

  1. @Input() properties
  2. @Output() properties
  3. public properties
  4. private properties
  5. constructor()
  6. Angular Life Cycle methods (e.g. ngOnInit())
  7. public methods
  8. private methods

E.g.:

@Component({
  selector: "app-some-component",
  templateUrl: "./some-component.component.html",
  styleUrls: ["./some-component.component.scss"],
})
export class SomeComponent implements OnInit {
  @Input() someInput: string = "";

  @Output() someOutput = new EventEmitter<string>();

  public somePublicProp: string | undefined;

  private _somePrivateProp: string | undefined;

  constructor() {}

  ngOnInit(): void {
    this.somePublicProp = "foo";
  }

  public somePublicInternalMethod(): void {}

  private somePrivateInternalMethod(): void {}
}

Dependency Injection

Injected Service Naming

As a rule of thumb, injected services should be labeled as private readonly, and follow the _lowerCamelCase naming convention. E.g.:

constructor(
    private readonly _someInjectedService: SomeInjectedService,
    private readonly _someOtherInjectedService: SomeOtherInjectedService
) {
    // ...
}

Component Architecture

Page Structure Styling

As a rule of thumb, smaller / individual page control components should not have page structure styling associated with them. The styling included should be the absolute bare minium for the component to render as expected, while the larger page components handle the placement of said components.

Take the following example, where we have a button that performs a specific action on a page. This function is used in several places in the app though, so we have broken this app out into a component.

<!-- DO THIS -->

<button class="some-button" (click)="doSomething()">Some Button</button>

<!-- DON'T DO THIS -->

<div class="row some-button-wrapper">
  <div class="col-12">
    <button class="some-button" (click)="doSomething()">Some Button</button>
  </div>
</div>

Embedding too much structural styling makes it more difficult to reuse the component elsewhere.

That way the component can be used elsewhere, and the page containing the component can handle the specific styling requirements therein:

<!-- some-page.component.html -->

<div class="row some-button-wrapper">
  <div class="col-4">...</div>
  <div class="col-4">...</div>
  <div class="col-4 some-button-wrapper">
    <app-some-button></app-some-button>
  </div>
</div>

Angular URI and Routing

Avoid using string interpolation

It is best practice to avoid using string interpolation in the routerLink directive. Instead, use the routerLink directive with an array of strings- which are your route segments. This will help avoid errors when refactoring the URI.

// you want to get to this URI: /admin/users/1234

// DONT DO THIS
this._router.createUrlTree([`/admin/users/${appUserGuid}`]);

// DO THIS
this._router.createUrlTree(["admin", "users", appUserGuid]);