Introducing resource
Angular 19 brings an exciting addition to its toolkit: the Resource API. This API is designed to simplify asynchronous data fetching and state management, making it more declarative and easier to integrate into Angular’s reactive ecosystem.
In this blog, we’ll explore:
- The benefits of the Resource API
- How it compares to traditional
HttpClient
implementations - A complete example using products data, showcasing filtering by category with
linkedSignal
What is the Resource API?
The Resource API leverages Angular’s reactivity model to provide:
- Declarative data fetching: Define and manage resources with minimal boilerplate.
- Automatic state management: Built-in handling of loading, errors, and data updates.
- Reactive signals: Seamless synchronization with Angular’s
signal
andlinkedSignal
.
How Does It Compare to the Traditional Approach?
The Old Way
In pre-Angular 19 applications, data was often fetched using HttpClient
within services, requiring manual state management. Here’s an example:
// Old service implementation
getProducts(): Observable<Product[]> {
return this.http.get<Product[]>('https://api.example.com/products');
}
// Old component implementation
this.productService.getProducts().subscribe({
next: (data) => { this.products = data; this.isLoading = false; },
error: (err) => { this.error = err.message; this.isLoading = false; }
});
Drawbacks
- Manual State Management: Developers had to handle loading, errors, and data updates manually in every component.
- Boilerplate Code: Each service and component required repetitive code for fetching data and managing states.
- Complexity with Derived States: Filtering and transforming data often required separate streams or additional logic.
- Inconsistent Practices: Different developers might manage states differently, leading to inconsistent patterns across the codebase.
The New Way with Resource API
With the Resource API, the repetitive parts of state management are handled automatically:
products = resource({
loader: async () => {
const response = await fetch('https://api.example.com/products');
if (!response.ok) {
throw new Error('Failed to fetch products');
}
return response.json();
},
});
Why It’s Better Long Term
- Declarative Syntax: The Resource API makes data fetching and state management part of the Angular reactivity model. Developers define what data they need and how it should react to changes, and Angular handles the rest.
- Built-In State Management: Automatic handling of loading, error, and data states simplifies component logic.
- Derived State with Signals: The seamless integration with
linkedSignal
allows for effortless creation of derived states (e.g., filtering products by category). - Reduced Boilerplate: Say goodbye to repetitive loading/error handling code in every component.
- Consistency: Provides a standard way to manage data across the application, making it easier to onboard new developers or refactor code.
- Future-Ready: The Resource API aligns with Angular’s long-term strategy of reactive, signal-based development, ensuring compatibility and smoother upgrades in the future.
Building a Product List with the Resource API
Let’s dive into a practical example: fetching and displaying products with filtering by category.
Service Implementation
Here’s how to set up the Resource API in your ProductService
:
import { Injectable, signal, resource } from '@angular/core';
import { Product, Response } from './Product';
@Injectable({
providedIn: 'root',
})
export class ProductService {
private apiUrl = 'https://dummyjson.com/products';
// Signal to trigger the resource loader
private trigger = signal<void>(undefined);
// Resource to fetch products
products = resource({
request: () => this.trigger,
loader: async () => {
const response = await fetch(this.apiUrl);
if (!response.ok) {
throw new Error('Failed to fetch products');
}
const data = response.json() as Promise<Response>;
return (await data).products;
},
});
// Method to reload products
reload() {
this.trigger.set(undefined);
}
}
Component with Linked Signals
In the component, linkedSignal
is used to manage derived states, like the list of categories and filtered products.
import { Component, effect, linkedSignal, signal } from '@angular/core';
import { ProductService } from '../product.service';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css'],
})
export class ProductListComponent {
productsResource = this.productService.products;
selectedCategory = signal<string>('all');
categories = linkedSignal(() => {
if (!this.productsResource.value()) return [];
return Array.from(
new Set(
this.productsResource.value()?.map((product) => product.category)
)
);
});
filteredProducts = linkedSignal(() => {
const category = this.selectedCategory();
if (category === 'all') return this.productsResource.value();
return this.productsResource.value()?.filter(
(product) => product.category === category
);
});
constructor(private productService: ProductService) {}
selectCategory(e: any) {
this.selectedCategory.set(e.target.value);
}
reload() {
this.selectedCategory.set('all');
this.productService.reload();
}
}
The Benefits in Action
- Automatic State Management: Loading, data, and error states are built into the Resource API.
- Simplified UI Logic: The use of
linkedSignal
ensures that the UI automatically updates when data or user selections change. - Consistency Across Features: The same declarative pattern can be used for other data resources, ensuring uniformity across the app.
Conclusion
Angular 19’s Resource API is a significant step forward for Angular developers. By combining declarative data fetching with reactive signals, it provides:
- Cleaner code
- Enhanced maintainability
- A more consistent developer experience
When compared to the traditional approach, the Resource API not only reduces boilerplate but also aligns with Angular’s vision for reactive, signal-driven development, ensuring its relevance for years to come.
If you’re still using the old way, now is the time to embrace the future with Angular 19. What do you think about the Resource API? Let’s discuss in the comments below!
Checkout complete code example here: https://github.com/kategable/stackblitz-starters-linkedSignal
and StackBlitz: https://stackblitz.com/~/github.com/kategable/stackblitz-starters-linkedSignal
get more Angularv19 here https://blog.angular.dev/meet-angular-v19-7b29dfd05b84