Most Angular apps load data over HTTP, keep some state on the client and collect input through forms. This chapter covers HttpClient, signal-based state, RxJS basics and reactive forms.
Setting up HttpClient
Register HttpClient once in app.config.ts. withFetch() makes it use the browser's Fetch API, which is recommended when you use server-side rendering:
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient, withFetch } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [provideHttpClient(withFetch())],
};
A data service
Keep HTTP calls in a service. HttpClient methods return Observables that send the request on subscribe and emit the parsed JSON:
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
export interface Todo {
id: number;
title: string;
completed: boolean;
}
@Injectable({ providedIn: 'root' })
export class TodoApi {
private readonly http = inject(HttpClient);
private readonly baseUrl = 'https://jsonplaceholder.typicode.com/todos';
list(limit = 10): Observable<Todo[]> {
const params = new HttpParams().set('_limit', limit);
return this.http.get<Todo[]>(this.baseUrl, { params });
}
create(title: string): Observable<Todo> {
return this.http.post<Todo>(this.baseUrl, { title, completed: false });
}
}
The type argument in get<Todo[]> informs TypeScript only; the response is not validated at runtime.
From Observables to signals
toSignal() subscribes to an Observable, exposes the latest value as a signal and unsubscribes when the component is destroyed:
import { Component, inject } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { TodoApi } from './todo-api';
@Component({
selector: 'app-todo-list',
template: `
@for (todo of todos(); track todo.id) {
<p>{{ todo.title }}</p>
} @empty {
<p>Loading...</p>
}
`,
})
export class TodoList {
private readonly api = inject(TodoApi);
protected readonly todos = toSignal(this.api.list(), { initialValue: [] });
}
Shared state with signals
For state that several components share, such as a cart, a service holding signals is often enough. Components read the exposed signals; only the service changes them:
import { Injectable, computed, signal } from '@angular/core';
export interface CartItem { id: number; price: number; qty: number; }
@Injectable({ providedIn: 'root' })
export class CartStore {
private readonly items = signal<CartItem[]>([]);
readonly all = this.items.asReadonly();
readonly total = computed(() => this.items().reduce((sum, item) => sum + item.price * item.qty, 0));
add(item: CartItem) {
this.items.update((list) => [...list, item]);
}
}
0 comentários
Fazer login · Faça login para deixar um comentário.