DEV Community

Martin Klingenberg
Martin Klingenberg

Posted on

What I should have known when starting to write angular 🔥

I have written angular for some years now and I am still learning. I know Angular is the framework everyone loves to hate, the Java of the frontend world. However, the likelyhood of ending up in an angular project is quite high. Let me take you through my most important tips to becoming a good angular developer.

No logic in your components

A component in angular has three files that should be focusing on rendering and only rendering. If you start adding a lot of business-logic into that component-code you will end up with code that is overly complicated and tests that are hard to maintain. If your component.ts-file exceeds 250 lines of code, it is time to rethink and refactor. Put logic into a service or event split the component into several smaller components.

Features === Modules

I remember my first angular project. It had one module in it. That is wrong on so many levels and my rule of thumb is that you should make modules for every new feature. And there should be no cross-feature imports.

RXJS is your friend

RXJS is a great tool for syncing major state of an application. State like the chosen project across the whole application. I remember doing a lot of subscriptions in my first application. And subscribing is not very good, let angular handle subscriptions. Below there are two examples:

Bad usage of observables

This example is using subscribe and is in my mind "duplicating" data and we even have a memory leak if the observable does not complete.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-bad',
  template: `
  <ul>
    <li *ngFor="let idea of data ">{{ idea.name }}</li>
  </ul>
  `,
  styles: []
})
export class BadComponent  {

  data: Idea[];

  constructor(private ideaService: IdeaService) {
    this.data$ = ideaService.getGoodIdeasFromAlv().subscribe(data => this.data = data);
  }
}
Enter fullscreen mode Exit fullscreen mode

Good usage of observables

This example is using the async-pipe and is much cleaner. No memory-leaks as angular is removing the subscription for us. the code is also more readable.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-good',
  template: `
  <ul>
    <li *ngFor="let idea of data$ | async">{{ idea.name}}</li>
  </ul>`,
  styles: []
})
export class GoodComponent  {

  data$: Observable<Idea[]>;

  constructor(private ideaService: IdeaService) {
    this.data$ = ideaService.getGoodIdeasFromAlv();
  }
}
Enter fullscreen mode Exit fullscreen mode

Quick tips about RXJS

  • Learn how to use map, switchMap, share, shareReplay mergeMap-operators
  • Learn why shareReplay can create memory-leaks
  • The less Behaviour-subjects / subjects you use, the better. Always rethink when adding new ones. You should hardly use any.
  • When using switchMap/mergeMap you should carry the initial state. Trust me, it will make code scale in the future.
class ExampleService {
  exampleId$ = BehaviourSubject(0);
  exampleResult$: Observable<{id: number, examples: string[]}>;

  constructor(private readonly httpClient: HttpClient) {
    this.exampleResult$ = this.exampleResultObservable();
  }

  private create exampleResultObservable() {
    exampleId.pipe(
      switchMap(id => this.httpClient.get(`somebackend/${id}`).pipe(map(response => ({
id,
examples: response,
}))
    )
  }

}
Enter fullscreen mode Exit fullscreen mode

A few quick tips to complete the article

Use reactive forms

Your solution is not as good as what comes from @angular/forms

Give your loops an index

This increases rendering performance. Use the trackBy-directive and thank me when your project scales.

Use pipes instead of functions

If you have a function in your component, formatting values, consider using a pipe instead. It is reusable and the performance is better.

ChangeDetection set to onPush

If you manage to follow the "good" example above, all your component state will be reactive. Using onPush makes change detection more conservative and more efficient.

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
Enter fullscreen mode Exit fullscreen mode

Have I missed something?

Feel free to pass a comment and I might include your suggestions

Top comments (1)

Collapse
 
emmysteven profile image
Emmy Steven

I’ll say angular is way more organised than most JavaScript frameworks.