Skip to content

Angular (20+) Request API based on Observable, Signal (global and local state management, effect, httpResource, input-pattern, model)

Notifications You must be signed in to change notification settings

leolanese/Angular-API-Observable-Signal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Angular (20+) Observable + Signals for handling API requests

πŸ”΄ 🟑 🟒 πŸš€

⏺ Goals AC's

⏺ Test legacy Angular Vs new modern Angular practices

Test API based on Observable, Signal (state management, effect, httpResource, input-pattern, model)

https://jsonplaceholder.typicode.com/posts

⏺ Test complex/nested API Requests

  1. Get all country names and display on the page: https://restcountries.com/v3.1/independent?fields=name

  2. Select a country and Show the flag: https://restcountries.com/v3.1/name/Grenada?fields=name,flags

  3. Search countries by language: https://restcountries.com/v3.1/lang/spanish?fields=name


πŸ”Έ Demo

Angular CLI: 20.1.5
Node: 22.13.1
Package Manager: npm 11.0.0
OS: darwin arm64

Angular: 20.1.6
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.2001.5
@angular-devkit/build-angular   20.1.5
@angular-devkit/core            20.1.5
@angular-devkit/schematics      20.1.5
@angular/cli                    20.1.5
@schematics/angular             20.1.5
rxjs                            7.8.2
typescript                      5.8.3
zone.js                         0.15.0

Modern practices latest final signal-based API is implementing πŸš€

βœ… @NgModule  β†’ Standalone component
βœ… *ngFor, *ngIf  β†’ Modern control flow: @if, @for
βœ… HttpClient β†’ HttpResource API for data fetching
βœ… ngOnInit() + subscribe() + contructor based inject β†’ Use reactive Signals + computed() 
βœ… contruct-based DI injection β†’ inject(HttpClient) 
βœ… Better Ts notation β†’ Protected + readonly template properties for protection and mutability control

βœ… RxJS / reactive streams β†’ `Signal-Based Component Architecture Pattern` (using signals, computed, and effects internally instead of Observables for local reactive state)
βœ… Flow / Two-Way Binding (Old Way) β†’ `Signal-input-pattern architecture flow` (signal parent ↔ child communication)

πŸ”Έ Example Solution Arquitecture

src/
└── app/
     β”œβ”€β”€ SoC/
          └── input/output   // Separation of Concern using Parent and Child, @Input()/@Output()
          └── input/output   // Separation of Concern using Parent and Child, input signal/@Output()
     β”œβ”€β”€ orphan-observable/  // single Component, managing API request using Observables
     β”œβ”€β”€ orphan-signal/      // single Component, managing API request using Signals
     β”œβ”€β”€ orphan-signal-simple/  // single Component, managing API request using Signal
     β”œβ”€β”€ orphan-signal-nested/  // single Component, managing complex API request using Signal
     β”œβ”€β”€ orphan-signal-httpresource/ // simple Component, managing API request using Signals with httpResouce asynchronous data fetching
     β”œβ”€β”€ orphan-signal--httpresource-reactiveForm/ // Shows how the new signals approach replaces the traditional RxJS pattern
     β”œβ”€β”€ orphan-signal-httpresource-signal/ // 100% fully signal-based. Using direct signal binding with [value] and (input). Simple event handler to update the signal
     β”œβ”€β”€ orphan-signal-input-pattern/ // full signal-based approach: 1-way binding
     β”œβ”€β”€ orphan-signal-model/ // full signal-based approach: 2-way binding
     |
     β”œβ”€β”€ app.component.ts
     β”œβ”€β”€ auth.interceptor.ts
     └── http.interceptor.ts

πŸ”Έ Technical mentions

🟑 Green solutions are 100% fully reactive signal-based which are Angular recommendations:

πŸ”΅ Reactive state management

  • All state is managed through signals in the service

πŸ”΅ Data Management:

  • No local component state variables that aren't signals
  • No RxJS Observables or Subjects

πŸ”΅ HTTP Handling:

  • Signal with httpresource, for automatic data fetching

πŸ”΅ Template Binding:

  • Replaces NgModel is part of the older Forms API, while signals represent Angular's future
  • All template expressions use signals (vehicleService.searchTerm(), vehicleService.isLoading(), etc.)
  • Uses modern Angular control flow (@if, @else, @for)

πŸ”΅ Data Flow:

Unidirectional Data Flow: clean, predictable, and performant! πŸš€

  • Use signal-input-pattern: [value] + (input) pattern: It's simply a combination of 1-way binding (Property [value]="searchSignal()" + event binding (input)="signal.set()") -- The Two Parts of Signal-Input-Pattern:
<!-- Template - Signal-Input-Pattern -->
<input 
  [value]="signalService.searchTerm()"  <!-- Signal β†’ View -->
  (input)="onSearch($event)"            <!-- View β†’ Signal -->
/>
    Signal β†’ View ([property] binding) = [value]="searchSignal()
    View   β†’ Signal (event() handler) = (input)="signal.set()"
  • Direct Signal Control (when is read = binding, when is updated = event handler)

Bidirectional Data Flow (model() implement 2-way binding simplify two-way binding boilerplate

πŸ”΅ Event Handling:

  • Input events directly update signals (this.vehicleService.searchTerm.set(value))
  • No intermediate transformations using RxJS operators

πŸ”΅ Service Implementation:

  • Uses httpResource for HTTP requests (instead HttpClient) This provides:
  • Automatically fetches data when the component initializes.
  • Handles loading, success, and error states without extra code.
  • Provides a .value() method to access the latest data.
  • Supports reloading with .reload().
  • Stays within the signals paradigm and use signals' effect() to automatically handle cleanup (instead OnInit/OnDestroy + No need for manual subscription management)

🟑 Other technical mentions

πŸ”΅ SoC This example demonstrates the separation of concerns between the: service (responsible for fetching data), smart component (responsible for handling business logic and passing data to the dummy component), dummy component (responsible for rendering the UI)

πŸ”΅ Modern StandAlone Components: I directly bootstrap the component itself, not its module. This is because standalone components have their own injectors and don't rely on a root module for dependency injection. Promotes code maintainability, reusability, and smaller application size.

πŸ”΅ Implemented TSP mechanism: I'm using Tree Shakeable Providers in Services by using the providedIn attribute, this will provide the benefits of both tree shaking performance and dependency injection, meaning that our services will not be included in the final bundle unless they are being used by other services or components. As a result we reduce the bundle size by removing unused code from the bundle.

πŸ”΅ RxJS

  • takeUntilDestroyed(this.destroyRef) to automatically unsubscribe when the component is destroyed, simplifying the cleanup process even further
  • shareReplay(1) because multiple components might subscribe to the same observable

πŸ”΅ Dependency Injection Pattern: I'm using Modern Dependency Injection functions, instead traditional constructor-based dependency injectionas result I will have a more Modular, Less Complex

πŸ”΅ Implement Caching: -- Cache API Service Calls Caches identical HTTP requests within a single component: I'm using shareReplay() to improve efficiency, ensuring that all subscribers receive the most recent data without triggering multiple HTTP requests.

πŸ”΅ DestroyRef & takeUntilDestroyed(): Angular 16+ I'm using provides a more declarative and efficient way to handle automatic cleanup tasks when a component or service is destroyed: takeUntilDestroyed(this.destroyRef) to automatically unsubscribe when the component is destroyed, simplifying the cleanup process even further

πŸ”΅ Function-based Interceptor (optional): It also showcases the usage of an interceptor to log HTTP requests and responses. While not necessary for this example, it can be useful for debugging and monitoring purposes (WIP)


πŸ’― Thanks!

Now, don't be an stranger. Let's stay in touch β€Ό

leolanese’s GitHub image
πŸ”˜ gitroll: LeoLanese
πŸ”˜ Linkedin: LeoLanese
πŸ”˜ Twitter: @LeoLanese
πŸ”˜ Blog: dev.to/leolanese
πŸ”˜ Questions / Suggestions / Recommendations: [email protected]

About

Angular (20+) Request API based on Observable, Signal (global and local state management, effect, httpResource, input-pattern, model)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published