Content is user-generated and unverified.
// ================================================== // 1. Basic resource() Function Usage // ================================================== import { Component, signal, resource } from '@angular/core'; import { HttpClient } from '@angular/common/http'; interface User { id: number; name: string; email: string; } @Component({ selector: 'app-user-profile', template: ` <div> <h2>User Profile</h2> <!-- Show loading state --> @if (userResource.isLoading()) { <p>Loading user data...</p> } <!-- Show error state --> @if (userResource.error()) { <p class="error">Error: {{ userResource.error()?.message }}</p> } <!-- Show data --> @if (userResource.value()) { <div class="user-card"> <h3>{{ userResource.value()?.name }}</h3> <p>Email: {{ userResource.value()?.email }}</p> <p>ID: {{ userResource.value()?.id }}</p> </div> } <button (click)="loadUser(2)">Load User 2</button> <button (click)="loadUser(3)">Load User 3</button> </div> ` }) export class UserProfileComponent { private http = inject(HttpClient); // Signal to track which user ID to load userId = signal(1); // Create a resource that depends on userId signal userResource = resource({ request: () => ({ id: this.userId() }), loader: async ({ request }) => { // Simulate API call with Promise const response = await fetch(`/api/users/${request.id}`); return response.json() as Promise<User>; } }); loadUser(id: number) { this.userId.set(id); // This will trigger the resource to reload } } // ================================================== // 2. Resource API Interface Usage // ================================================== import { Resource, ResourceStatus } from '@angular/core'; @Component({ selector: 'app-data-manager', template: ` <div> <h2>Data Manager</h2> <!-- Generic resource display --> <div class="resource-info"> <p>Status: {{ getStatusText(dataResource.status()) }}</p> <p>Is Loading: {{ dataResource.isLoading() }}</p> <p>Has Error: {{ !!dataResource.error() }}</p> </div> @if (dataResource.value()) { <pre>{{ dataResource.value() | json }}</pre> } <button (click)="refreshData()">Refresh Data</button> </div> ` }) export class DataManagerComponent { private http = inject(HttpClient); // Using Resource API interface for type safety dataResource: Resource<any> = resource({ loader: async () => { // Simulate async operation await new Promise(resolve => setTimeout(resolve, 1000)); return { timestamp: new Date().toISOString(), data: 'Sample data loaded!' }; } }); // Helper method to work with Resource API getStatusText(status: ResourceStatus): string { switch (status) { case ResourceStatus.Idle: return 'Idle'; case ResourceStatus.Loading: return 'Loading'; case ResourceStatus.Resolved: return 'Resolved'; case ResourceStatus.Error: return 'Error'; case ResourceStatus.Reloading: return 'Reloading'; default: return 'Unknown'; } } refreshData() { this.dataResource.reload(); } } // ================================================== // 3. Advanced resource() with Dependencies // ================================================== @Component({ selector: 'app-posts-list', template: ` <div> <h2>Posts by Category</h2> <select (change)="onCategoryChange($event)"> <option value="">All Categories</option> <option value="tech">Technology</option> <option value="news">News</option> <option value="sports">Sports</option> </select> @if (postsResource.isLoading()) { <div class="loading">Loading posts...</div> } @if (postsResource.error()) { <div class="error"> Failed to load posts: {{ postsResource.error()?.message }} <button (click)="postsResource.reload()">Retry</button> </div> } @if (postsResource.value()) { <div class="posts-grid"> @for (post of postsResource.value(); track post.id) { <div class="post-card"> <h3>{{ post.title }}</h3> <p>{{ post.excerpt }}</p> <small>Category: {{ post.category }}</small> </div> } </div> } </div> ` }) export class PostsListComponent { private http = inject(HttpClient); // Signals for filtering selectedCategory = signal<string>(''); searchTerm = signal<string>(''); // Resource with multiple dependencies postsResource = resource({ request: () => ({ category: this.selectedCategory(), search: this.searchTerm() }), loader: async ({ request, abortSignal }) => { // Build query parameters const params = new URLSearchParams(); if (request.category) params.set('category', request.category); if (request.search) params.set('search', request.search); // Use abort signal for cancellation const response = await fetch(`/api/posts?${params}`, { signal: abortSignal }); if (!response.ok) { throw new Error(`Failed to fetch posts: ${response.statusText}`); } return response.json(); } }); onCategoryChange(event: Event) { const target = event.target as HTMLSelectElement; this.selectedCategory.set(target.value); } } // ================================================== // 4. Using rxResource() with Observables // ================================================== import { rxResource } from '@angular/core'; import { switchMap, catchError } from 'rxjs/operators'; import { of } from 'rxjs'; @Component({ selector: 'app-reactive-data', template: ` <div> <h2>Reactive Data with rxResource</h2> <input #searchInput (input)="searchQuery.set(searchInput.value)" placeholder="Search..." /> @if (searchResource.isLoading()) { <div>Searching...</div> } @if (searchResource.value()) { <div class="results"> @for (item of searchResource.value(); track item.id) { <div class="result-item">{{ item.title }}</div> } </div> } </div> ` }) export class ReactiveDataComponent { private http = inject(HttpClient); searchQuery = signal(''); // Using rxResource with Observable searchResource = rxResource({ request: () => ({ query: this.searchQuery() }), loader: ({ request }) => { if (!request.query) { return of([]); } return this.http.get<any[]>(`/api/search?q=${request.query}`).pipe( catchError(error => { console.error('Search error:', error); return of([]); }) ); } }); } // ================================================== // 5. Resource API Type Guards and Utilities // ================================================== import { ResourceRef } from '@angular/core'; // Utility functions for working with Resource API export class ResourceUtils { // Type guard to check if resource has data static hasData<T>(resource: Resource<T>): resource is Resource<T> & { value(): T } { return resource.status() === ResourceStatus.Resolved && resource.value() !== undefined; } // Type guard to check if resource is in error state static hasError<T>(resource: Resource<T>): resource is Resource<T> & { error(): Error } { return resource.status() === ResourceStatus.Error && resource.error() !== undefined; } // Generic resource state handler static handleResourceState<T>( resource: Resource<T>, handlers: { loading?: () => void; error?: (error: Error) => void; success?: (data: T) => void; } ) { if (resource.isLoading() && handlers.loading) { handlers.loading(); } else if (this.hasError(resource) && handlers.error) { handlers.error(resource.error()); } else if (this.hasData(resource) && handlers.success) { handlers.success(resource.value()); } } } // ================================================== // 6. Custom Resource Hook Pattern // ================================================== // Custom composable for user data export function useUserData(userId: Signal<number>) { const http = inject(HttpClient); return resource({ request: () => ({ id: userId() }), loader: async ({ request }) => { const response = await fetch(`/api/users/${request.id}`); if (!response.ok) { throw new Error(`User not found: ${response.status}`); } return response.json() as Promise<User>; } }); } // Usage in component @Component({ selector: 'app-user-details', template: ` <div> @if (userResource.isLoading()) { <p>Loading user...</p> } @if (userResource.error()) { <p>Error: {{ userResource.error()?.message }}</p> } @if (userResource.value()) { <h2>{{ userResource.value()?.name }}</h2> } </div> ` }) export class UserDetailsComponent { userId = signal(1); userResource = useUserData(this.userId); }
Content is user-generated and unverified.
    Angular 19 Resource API Examples | Claude