DEV Community

Alex Spinov
Alex Spinov

Posted on

Angular Has a Free API You Should Know About

Angular's latest versions have introduced powerful features that many developers haven't explored yet — signals, deferred loading, SSR with hydration, and the new control flow syntax.

Signals — Fine-Grained Reactivity

import { Component, signal, computed, effect } from "@angular/core"

@Component({
  selector: "app-counter",
  template: `
    <p>Count: {{ count() }}</p>
    <p>Doubled: {{ doubled() }}</p>
    <button (click)="increment()">+1</button>
  `
})
export class CounterComponent {
  count = signal(0)
  doubled = computed(() => this.count() * 2)

  constructor() {
    effect(() => {
      console.log(`Count changed: ${this.count()}`)
    })
  }

  increment() {
    this.count.update(c => c + 1)
  }
}
Enter fullscreen mode Exit fullscreen mode

New Control Flow

@Component({
  template: `
    @if (user()) {
      <h1>Welcome, {{ user().name }}</h1>

      @for (item of items(); track item.id) {
        <div class="item">{{ item.name }} - {{ item.price | currency }}</div>
      } @empty {
        <p>No items found</p>
      }
    } @else {
      <app-login />
    }

    @switch (status()) {
      @case ("loading") { <app-spinner /> }
      @case ("error") { <app-error [message]="error()" /> }
      @case ("success") { <app-dashboard [data]="data()" /> }
    }
  `
})
Enter fullscreen mode Exit fullscreen mode

HttpClient — Type-Safe HTTP

import { HttpClient } from "@angular/common/http"
import { inject } from "@angular/core"

interface User { id: number; name: string; email: string }

export class UserService {
  private http = inject(HttpClient)

  getUsers() {
    return this.http.get<User[]>("/api/users")
  }

  createUser(user: Partial<User>) {
    return this.http.post<User>("/api/users", user)
  }

  updateUser(id: number, data: Partial<User>) {
    return this.http.patch<User>(`/api/users/${id}`, data)
  }

  deleteUser(id: number) {
    return this.http.delete(`/api/users/${id}`)
  }
}
Enter fullscreen mode Exit fullscreen mode

Deferred Loading

Lazy-load components based on triggers:

@Component({
  template: `
    <h1>Dashboard</h1>

    @defer (on viewport) {
      <app-analytics-chart />
    } @placeholder {
      <div class="skeleton">Loading chart...</div>
    } @loading (minimum 500ms) {
      <app-spinner />
    }

    @defer (on interaction) {
      <app-comments [postId]="postId" />
    } @placeholder {
      <button>Load Comments</button>
    }

    @defer (on timer(3s)) {
      <app-recommendations />
    }
  `
})
Enter fullscreen mode Exit fullscreen mode

SSR with Hydration

// app.config.ts
import { provideClientHydration, withEventReplay } from "@angular/platform-browser"

export const appConfig = {
  providers: [
    provideClientHydration(withEventReplay())
  ]
}
Enter fullscreen mode Exit fullscreen mode

Resource & rxResource (Angular 19+)

import { resource, signal } from "@angular/core"

@Component({
  template: `
    @if (userResource.isLoading()) {
      <app-spinner />
    } @else if (userResource.error()) {
      <p>Error: {{ userResource.error() }}</p>
    } @else {
      <h1>{{ userResource.value().name }}</h1>
    }
  `
})
export class UserComponent {
  userId = signal("1")

  userResource = resource({
    request: this.userId,
    loader: async ({ request: id }) => {
      const res = await fetch(`/api/users/${id}`)
      return res.json()
    }
  })
}
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  • Signals for fine-grained reactivity without RxJS
  • New control flow (@if, @for, @switch) replaces *ngIf/*ngFor
  • Deferred loading (@defer) for lazy component loading
  • SSR hydration with event replay
  • resource() for declarative async data fetching
  • Standalone components — no NgModules needed

Explore Angular docs for the complete API.


Building web scrapers or data pipelines? Check out my Apify actors for ready-made solutions, or email spinov001@gmail.com for custom development.

Top comments (0)