<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Davide Passafaro</title>
    <description>The latest articles on DEV Community by Davide Passafaro (@davidepassafaro).</description>
    <link>https://dev.to/davidepassafaro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F775852%2Fafd61a9c-ee2d-41c0-a227-551b790190e8.png</url>
      <title>DEV Community: Davide Passafaro</title>
      <link>https://dev.to/davidepassafaro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidepassafaro"/>
    <language>en</language>
    <item>
      <title>Angular Meets Generative AI: Best Practices Made Easy</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Tue, 26 Aug 2025 07:27:28 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/angular-meets-generative-ai-best-practices-made-easy-1f2e</link>
      <guid>https://dev.to/playfulprogramming-angular/angular-meets-generative-ai-best-practices-made-easy-1f2e</guid>
      <description>&lt;p&gt;The use of &lt;strong&gt;generative AI&lt;/strong&gt; to produce code is becoming increasingly popular in the developer world. From creating quick prototypes to scaffolding entire features, AI tools are no longer just assistants, they’re starting to become part of our workflow.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Angular v20.2&lt;/strong&gt;, a new &lt;strong&gt;CLI command&lt;/strong&gt; allows you to generate a dedicated &lt;strong&gt;configuration file for AI models&lt;/strong&gt;. This file defines &lt;strong&gt;project-specific guidelines&lt;/strong&gt;, enabling generative AI to apply &lt;strong&gt;best practices&lt;/strong&gt;, follow established &lt;strong&gt;coding patterns&lt;/strong&gt;, and implement new functionality while remaining consistent with your codebase.&lt;/p&gt;

&lt;p&gt;Let’s walk through how to generate this file and explore the set of rules it contains.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 Generating the AI Configuration Files
&lt;/h2&gt;

&lt;p&gt;Starting with &lt;strong&gt;Angular CLI v20.2&lt;/strong&gt;, when creating a new project, the CLI prompts you to choose whether to include an &lt;strong&gt;AI configuration file&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng new app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll then be prompted to choose one or more &lt;strong&gt;AI tools&lt;/strong&gt; to configure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;? Which AI tools &lt;span class="k"&gt;do &lt;/span&gt;you want to configure with Angular best practices? 
  See: https://angular.dev/ai/develop-with-ai

❯ ◉ None  
  ◯ Claude                 &lt;span class="o"&gt;[&lt;/span&gt; https://docs.anthropic.com/en/docs/claude-code/memory &lt;span class="o"&gt;]&lt;/span&gt;  
  ◯ Cursor                 &lt;span class="o"&gt;[&lt;/span&gt; https://docs.cursor.com/en/context/rules &lt;span class="o"&gt;]&lt;/span&gt;  
  ◯ Gemini                 &lt;span class="o"&gt;[&lt;/span&gt; https://ai.google.dev/gemini-api/docs &lt;span class="o"&gt;]&lt;/span&gt;  
  ◯ GitHub Copilot         &lt;span class="o"&gt;[&lt;/span&gt; https://code.visualstudio.com/docs/copilot/copilot-customization#_custom-instructions &lt;span class="o"&gt;]&lt;/span&gt;  
  ◯ JetBrains AI Assistant &lt;span class="o"&gt;[&lt;/span&gt; https://www.jetbrains.com/help/junie/customize-guidelines.html &lt;span class="o"&gt;]&lt;/span&gt;  
  ◯ Windsurf               &lt;span class="o"&gt;[&lt;/span&gt; https://docs.windsurf.com/windsurf/cascade/memories#rules &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;Angular CLI&lt;/strong&gt; will generate a separate &lt;strong&gt;configuration file&lt;/strong&gt; for each tool you select, placing it in its designated path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gemini → .gemini/GEMINI.md&lt;/li&gt;
&lt;li&gt;Copilot → .github/copilot-instructions.md&lt;/li&gt;
&lt;li&gt;Claude → .claude/CLAUDE.md&lt;/li&gt;
&lt;li&gt;Cursor → .cursor/rules/cursor.mdc&lt;/li&gt;
&lt;li&gt;JetBrains → .junie/guidelines.md&lt;/li&gt;
&lt;li&gt;Windsurf → .windsurf/rules/guidelines.md&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you already know which &lt;strong&gt;AI tool&lt;/strong&gt; you want to configure, you can skip the prompt and pass it directly as an option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng new app &lt;span class="nt"&gt;--ai-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gemini
ng new app &lt;span class="nt"&gt;--ai-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;copilot
ng new app &lt;span class="nt"&gt;--ai-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;claude
ng new app &lt;span class="nt"&gt;--ai-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cursor
ng new app &lt;span class="nt"&gt;--ai-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;jetbrains
ng new app &lt;span class="nt"&gt;--ai-config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;windsurf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you skip this step, you can always add the configuration later in an existing project using one of the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start the prompt to choose which AI tool(s) to configure&lt;/span&gt;
ng generate ai-config

&lt;span class="c"&gt;# Generate the AI configuration for a specific tool (Gemini in this example)&lt;/span&gt;
ng generate ai-config &lt;span class="nt"&gt;--tool&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 Let’s Analyze the Configuration File
&lt;/h2&gt;

&lt;p&gt;The generated files have the same format for each selected AI tool.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: the Cursor file also includes some metadata, nothing to worry about&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  AI context for code generation
&lt;/h3&gt;

&lt;p&gt;At the top of the file, a &lt;strong&gt;context&lt;/strong&gt; is given to the AI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are an expert in TypeScript, Angular, and scalable web application development. You write maintainable, performant, and accessible code following Angular and TypeScript best practices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This helps guide the AI to produce suggestions and scaffolding that align with the &lt;strong&gt;conventions&lt;/strong&gt; and &lt;strong&gt;best practices&lt;/strong&gt; for your Angular project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sections and rules
&lt;/h3&gt;

&lt;p&gt;The rest of the file is then divided into several &lt;strong&gt;sections&lt;/strong&gt;, each defining more &lt;strong&gt;context&lt;/strong&gt; and &lt;strong&gt;rules&lt;/strong&gt; for a specific area of development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TypeScript Best Practices&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Angular Best Practices&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Components&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State Management&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Templates&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Services&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the full configuration file with all sections and rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## TypeScript Best Practices&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Use strict type checking
&lt;span class="p"&gt;-&lt;/span&gt; Prefer type inference when the type is obvious
&lt;span class="p"&gt;-&lt;/span&gt; Avoid the &lt;span class="sb"&gt;`any`&lt;/span&gt; type; use &lt;span class="sb"&gt;`unknown`&lt;/span&gt; when type is uncertain

&lt;span class="gu"&gt;## Angular Best Practices&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Always use standalone components over NgModules
&lt;span class="p"&gt;-&lt;/span&gt; Must NOT set &lt;span class="sb"&gt;`standalone: true`&lt;/span&gt; inside Angular decorators. It's the default.
&lt;span class="p"&gt;-&lt;/span&gt; Use signals for state management
&lt;span class="p"&gt;-&lt;/span&gt; Implement lazy loading for feature routes
&lt;span class="p"&gt;-&lt;/span&gt; Do NOT use the &lt;span class="sb"&gt;`@HostBinding`&lt;/span&gt; and &lt;span class="sb"&gt;`@HostListener`&lt;/span&gt; decorators. Put host bindings inside the &lt;span class="sb"&gt;`host`&lt;/span&gt; object of the &lt;span class="sb"&gt;`@Component`&lt;/span&gt; or &lt;span class="sb"&gt;`@Directive`&lt;/span&gt; decorator instead
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`NgOptimizedImage`&lt;/span&gt; for all static images.
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="sb"&gt;`NgOptimizedImage`&lt;/span&gt; does not work for inline base64 images.

&lt;span class="gu"&gt;## Components&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Keep components small and focused on a single responsibility
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`input()`&lt;/span&gt; and &lt;span class="sb"&gt;`output()`&lt;/span&gt; functions instead of decorators
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`computed()`&lt;/span&gt; for derived state
&lt;span class="p"&gt;-&lt;/span&gt; Set &lt;span class="sb"&gt;`changeDetection: ChangeDetectionStrategy.OnPush`&lt;/span&gt; in &lt;span class="sb"&gt;`@Component`&lt;/span&gt; decorator
&lt;span class="p"&gt;-&lt;/span&gt; Prefer inline templates for small components
&lt;span class="p"&gt;-&lt;/span&gt; Prefer Reactive forms instead of Template-driven ones
&lt;span class="p"&gt;-&lt;/span&gt; Do NOT use &lt;span class="sb"&gt;`ngClass`&lt;/span&gt;, use &lt;span class="sb"&gt;`class`&lt;/span&gt; bindings instead
&lt;span class="p"&gt;-&lt;/span&gt; Do NOT use &lt;span class="sb"&gt;`ngStyle`&lt;/span&gt;, use &lt;span class="sb"&gt;`style`&lt;/span&gt; bindings instead

&lt;span class="gu"&gt;## State Management&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Use signals for local component state
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`computed()`&lt;/span&gt; for derived state
&lt;span class="p"&gt;-&lt;/span&gt; Keep state transformations pure and predictable
&lt;span class="p"&gt;-&lt;/span&gt; Do NOT use &lt;span class="sb"&gt;`mutate`&lt;/span&gt; on signals, use &lt;span class="sb"&gt;`update`&lt;/span&gt; or &lt;span class="sb"&gt;`set`&lt;/span&gt; instead

&lt;span class="gu"&gt;## Templates&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Keep templates simple and avoid complex logic
&lt;span class="p"&gt;-&lt;/span&gt; Use native control flow (&lt;span class="sb"&gt;`@if`&lt;/span&gt;, &lt;span class="sb"&gt;`@for`&lt;/span&gt;, &lt;span class="sb"&gt;`@switch`&lt;/span&gt;) instead of &lt;span class="sb"&gt;`*ngIf`&lt;/span&gt;, &lt;span class="sb"&gt;`*ngFor`&lt;/span&gt;, &lt;span class="sb"&gt;`*ngSwitch`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use the async pipe to handle observables

&lt;span class="gu"&gt;## Services&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Design services around a single responsibility
&lt;span class="p"&gt;-&lt;/span&gt; Use the &lt;span class="sb"&gt;`providedIn: 'root'`&lt;/span&gt; option for singleton services
&lt;span class="p"&gt;-&lt;/span&gt; Use the &lt;span class="sb"&gt;`inject()`&lt;/span&gt; function instead of constructor injection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, each section contains non-opinionated rules and focuses almost exclusively on using the new Angular APIs over the older ones.&lt;/p&gt;

&lt;p&gt;For example, prefer the &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-control-flow-the-complete-guide-1pan"&gt;new Angular Control Flow&lt;/a&gt;&lt;/strong&gt; directives (&lt;code&gt;@if&lt;/code&gt;, &lt;code&gt;@for&lt;/code&gt;, &lt;code&gt;@switch&lt;/code&gt;) instead of &lt;code&gt;*ngIf&lt;/code&gt;, &lt;code&gt;*ngFor&lt;/code&gt;, and &lt;code&gt;*ngSwitch&lt;/code&gt;. Similarly, use Signals and the &lt;a href="https://dev.to/davidepassafaro/angular-signal-inputs-road-to-signal-components-32cl"&gt;&lt;code&gt;input()&lt;/code&gt;&lt;/a&gt;/&lt;a href="https://dev.to/davidepassafaro/angular-new-output-function-44f1"&gt;&lt;code&gt;output()&lt;/code&gt;&lt;/a&gt; APIs over their older alternatives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add your own rules
&lt;/h3&gt;

&lt;p&gt;If you’d like, you’re free to &lt;strong&gt;extend the configuration&lt;/strong&gt; with your own rules, such as &lt;strong&gt;naming conventions&lt;/strong&gt;, &lt;strong&gt;ordering preferences&lt;/strong&gt;, or any other &lt;strong&gt;coding standards&lt;/strong&gt; that better fit your team’s workflow.&lt;/p&gt;

&lt;p&gt;You can &lt;strong&gt;either add new rules to the existing sections or create entirely new sections&lt;/strong&gt; if needed.&lt;/p&gt;

&lt;p&gt;For instance, a dedicated &lt;strong&gt;NgRx section&lt;/strong&gt; could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## NgRx Best Practices&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Use feature-specific state slices rather than a single global state object.
&lt;span class="p"&gt;-&lt;/span&gt; Always define action types using a &lt;span class="sb"&gt;`[Feature] Event`&lt;/span&gt; convention (e.g., &lt;span class="sb"&gt;`[Auth] Login Success`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; Group effects logically per feature and keep side-effects outside of components.
&lt;span class="p"&gt;-&lt;/span&gt; Avoid deeply nested state structures; normalize data when possible.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file should be treated &lt;strong&gt;like code, but written in natural language&lt;/strong&gt;. Structuring it thoughtfully and keeping it &lt;strong&gt;clean&lt;/strong&gt; and &lt;strong&gt;organized&lt;/strong&gt; is &lt;strong&gt;not trivial&lt;/strong&gt; and should be done with care, &lt;strong&gt;just like any other code file&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📖 Useful Links for Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/angular/angular-cli/pull/30763" rel="noopener noreferrer"&gt;Add schematics to generate ai context files — Angular CLI PR #30763&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://angular.dev/ai/develop-with-ai" rel="noopener noreferrer"&gt;Angular.dev — LLM prompts and AI IDE setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎉 Thanks for Reading! Until Next Time! 🚀
&lt;/h2&gt;

&lt;p&gt;If you found this useful, I’d love to hear your thoughts. Drop a &lt;strong&gt;comment&lt;/strong&gt;, give a &lt;strong&gt;like&lt;/strong&gt;, or &lt;strong&gt;follow&lt;/strong&gt; me to stay in the loop. I’ll appreciate it! 👏&lt;/p&gt;

&lt;p&gt;Share it with friends, colleagues, or anyone passionate about Angular.&lt;br&gt;
Let’s &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;connect on LinkedIn&lt;/a&gt;&lt;/strong&gt;! 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular Deep Signal: Modeling State in Depth</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Mon, 04 Aug 2025 21:01:24 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/angular-deep-signal-modeling-state-in-depth-bb9</link>
      <guid>https://dev.to/davidepassafaro/angular-deep-signal-modeling-state-in-depth-bb9</guid>
      <description>&lt;p&gt;With the introduction of &lt;strong&gt;Signals&lt;/strong&gt; in Angular, state management has become much clearer, more maintainable, and predictable.&lt;/p&gt;

&lt;p&gt;Thanks to primitives like &lt;strong&gt;&lt;code&gt;signal()&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt;, you can model and derive data effectively while keeping dependencies between different parts of the state under control.&lt;/p&gt;

&lt;p&gt;However, &lt;strong&gt;updating deep values of a Signal is not as straightforward&lt;/strong&gt;, often requiring manual interventions on the parent state.&lt;/p&gt;

&lt;p&gt;To address this need, the Angular team is currently developing a new Signal primitive that allows &lt;strong&gt;reactive access and modification of deep properties&lt;/strong&gt; within another Signal: &lt;strong&gt;Deep Signal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, you'll explore what &lt;strong&gt;Deep Signals&lt;/strong&gt; are, how they work, and why they can help simplify the code in your Angular applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Accessing and Updating Deep State
&lt;/h2&gt;

&lt;p&gt;Let’s consider an application that manages a user’s personal data.&lt;/p&gt;

&lt;p&gt;This is a very common scenario, where the application state contains information such as the user’s &lt;strong&gt;first name&lt;/strong&gt;, &lt;strong&gt;last name&lt;/strong&gt;, and &lt;strong&gt;city&lt;/strong&gt; of residence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Davide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Passafaro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt;, you can easily derive values from this state, for example, to get the user’s &lt;strong&gt;first name&lt;/strong&gt; and &lt;strong&gt;city&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userCity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, suppose you want to allow the user to update their info via a form.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;strong&gt;&lt;code&gt;ngModel&lt;/code&gt;&lt;/strong&gt;, you can directly bind the form inputs to the Signals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Nome: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;[(ngModel)]=&lt;/span&gt;&lt;span class="s"&gt;"userName()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Città: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;[(ngModel)]=&lt;/span&gt;&lt;span class="s"&gt;"userCity()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, here arises a problem: values derived from &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt; are &lt;strong&gt;read-only&lt;/strong&gt; and therefore cannot be updated directly.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;ngModel&lt;/code&gt;&lt;/strong&gt; directive, on the other hand, expects to be able to both read from and write to the associated model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linked Signal: a workaround, not exactly a solution
&lt;/h3&gt;

&lt;p&gt;To update a deep property, you are forced to manually modify the parent state by creating a dedicated function.&lt;/p&gt;

&lt;p&gt;Following the example, you can define an &lt;strong&gt;&lt;code&gt;updateCity&lt;/code&gt;&lt;/strong&gt; function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateCity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newCity&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, you then connect this function to the form input, explicitly handling the change event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
  Città:
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
    &lt;span class="na"&gt;[ngModel]=&lt;/span&gt;&lt;span class="s"&gt;"userCity()"&lt;/span&gt;
    &lt;span class="na"&gt;(ngModelChange)=&lt;/span&gt;&lt;span class="s"&gt;"updateCity($event)"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solution, although functional, &lt;strong&gt;is not inherently reactive&lt;/strong&gt;: it relies on an explicit call to the &lt;strong&gt;&lt;code&gt;updateCity()&lt;/code&gt;&lt;/strong&gt; function, leaving you responsible for maintaining state consistency.&lt;/p&gt;

&lt;p&gt;And there are no guarantees that this will always happen systematically.&lt;/p&gt;

&lt;p&gt;To work around this limitation, you can use &lt;strong&gt;&lt;code&gt;linkedSignal()&lt;/code&gt;&lt;/strong&gt;: a function that allows &lt;strong&gt;creating a derived Signal that is also writable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By combining this with an &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt;, you can achieve a sort of two-way synchronization between the derived value and the main state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Davide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Passafaro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userCity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;linkedSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({...&lt;/span&gt;&lt;span class="nf"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;userCity&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this scenario, the value of &lt;strong&gt;&lt;code&gt;userCity()&lt;/code&gt;&lt;/strong&gt; is derived from &lt;strong&gt;&lt;code&gt;userModel()&lt;/code&gt;&lt;/strong&gt;, but it can also be directly updated via &lt;strong&gt;&lt;code&gt;userCity.set()&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Your form becomes much more straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Nome: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;[(ngModel)]=&lt;/span&gt;&lt;span class="s"&gt;"userName()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Città: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;[(ngModel)]=&lt;/span&gt;&lt;span class="s"&gt;"userCity()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every change to &lt;strong&gt;&lt;code&gt;userCity()&lt;/code&gt;&lt;/strong&gt; is intercepted by the &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt;, which accordingly updates the main state. This way, you achieve a &lt;strong&gt;manual&lt;/strong&gt;, &lt;strong&gt;homemade two-way synchronization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Awesome!!!&lt;/p&gt;

&lt;p&gt;Well, not exactly…&lt;/p&gt;

&lt;p&gt;You do solve the problem, but at the cost of increased complexity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why do you use &lt;strong&gt;&lt;code&gt;linkedSignal()&lt;/code&gt;&lt;/strong&gt; instead of a simple &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;And why do you need that &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are all questions that future maintainers of the code, or even the future ourselves, might ask when faced with unclear code that doesn’t clearly explain the “why” behind the choices made.&lt;/p&gt;

&lt;p&gt;For this reason, we need a more robust, &lt;strong&gt;natively bidirectional solution&lt;/strong&gt; that doesn’t rely on manual workarounds and remains clear and explicit for anyone who reads or maintains the code in the future.&lt;/p&gt;

&lt;p&gt;This is exactly where &lt;strong&gt;Deep Signals&lt;/strong&gt; come into play.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧬 The new Deep Signal primitive
&lt;/h2&gt;

&lt;p&gt;With the new &lt;strong&gt;Deep Signal&lt;/strong&gt; primitive, Angular introduces a robust and declarative solution for managing deep state.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Deep Signal&lt;/strong&gt; allows you to directly &lt;strong&gt;access and modify nested properties inside a Signal reactively and bidirectionally&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to create a Deep Signal
&lt;/h3&gt;

&lt;p&gt;As with other primitives, Angular provides a dedicated function, &lt;strong&gt;&lt;code&gt;deepSignal()&lt;/code&gt;&lt;/strong&gt;, to create a &lt;strong&gt;Deep Signal&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Davide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Passafaro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userCity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deepSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;&lt;code&gt;deepSignal()&lt;/code&gt;&lt;/strong&gt; function accepts two parameters: the &lt;strong&gt;parent Signal&lt;/strong&gt; containing the state from which you want to extract a property, and the &lt;strong&gt;key&lt;/strong&gt; that identifies that property within the structure, expressed either as a &lt;strong&gt;&lt;code&gt;string&lt;/code&gt;&lt;/strong&gt; or as a &lt;strong&gt;Signal&lt;/strong&gt; containing a &lt;strong&gt;&lt;code&gt;string&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The value returned by &lt;strong&gt;&lt;code&gt;deepSignal()&lt;/code&gt;&lt;/strong&gt; is effectively a &lt;strong&gt;bidirectional Signal&lt;/strong&gt;: you can read its value just like with a normal &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt;, but you can also update it directly using the &lt;strong&gt;&lt;code&gt;set()&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;update()&lt;/code&gt;&lt;/strong&gt; methods, without having to manually reconstruct the parent state.&lt;/p&gt;

&lt;p&gt;In the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;userCity&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints "Rome"&lt;/span&gt;

&lt;span class="nx"&gt;userCity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Turin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// Updates userModel().city&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Being a &lt;strong&gt;Signal&lt;/strong&gt;, it can then be used seamlessly within templates as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Città: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;[(ngModel)]=&lt;/span&gt;&lt;span class="s"&gt;"userCity()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;&lt;code&gt;ngModel&lt;/code&gt;&lt;/strong&gt; directive is now fully compatible: every change to the input field will directly update the deep state inside &lt;strong&gt;&lt;code&gt;userModel()&lt;/code&gt;&lt;/strong&gt;, and vice versa.&lt;/p&gt;

&lt;p&gt;This approach drastically reduces the necessary boilerplate and improves code readability and consistency, making access and updates to nested state portions more &lt;strong&gt;straightforward&lt;/strong&gt;, &lt;strong&gt;explicit&lt;/strong&gt;, and &lt;strong&gt;safe&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance of Deep Signals
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Deep Signals&lt;/strong&gt; are not only more convenient to use but also bring significant &lt;strong&gt;performance advantages&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As previously said, without them, updating a nested property requires updating the &lt;strong&gt;parent Signal&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Davide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Passafaro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({...&lt;/span&gt;&lt;span class="nf"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Turin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that &lt;strong&gt;even the smallest change&lt;/strong&gt;, like updating just the &lt;strong&gt;&lt;code&gt;city&lt;/code&gt;&lt;/strong&gt; property, &lt;strong&gt;will trigger all effects and derived states&lt;/strong&gt; that depend on any part of the parent &lt;strong&gt;&lt;code&gt;userModel&lt;/code&gt;&lt;/strong&gt; state.&lt;/p&gt;

&lt;p&gt;Therefore, even those only interested in &lt;strong&gt;&lt;code&gt;name&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;lastname&lt;/code&gt;&lt;/strong&gt; will be notified, and every derived state will be recalculated. These will then detect that their data hasn’t actually changed and will skip further updates.&lt;/p&gt;

&lt;p&gt;But still, the performance cost remains significant, especially in applications with complex states or many connected effects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deep Signal&lt;/strong&gt; solves this problem through a more granular and targeted dependency management: it updates nested properties directly, notifying only those listening to that specific portion of the state.&lt;/p&gt;

&lt;p&gt;This way, only the effects and derived states that care about the modified property are notified, drastically reducing the number of unnecessary notifications and recalculations, with clear performance benefits.&lt;/p&gt;

&lt;p&gt;But that’s not all.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 Structural Signals: When Structure Matters
&lt;/h2&gt;

&lt;p&gt;The introduction of &lt;strong&gt;Deep Signals&lt;/strong&gt; paves the way for another very useful &lt;strong&gt;Signal&lt;/strong&gt; primitive: &lt;strong&gt;Structural Signals&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Structural Signal&lt;/strong&gt; is derived from a &lt;strong&gt;&lt;code&gt;WritableSignal&lt;/code&gt;&lt;/strong&gt; and returns its full value, similar to a &lt;strong&gt;Computed Signal&lt;/strong&gt;, in this form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Davide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Passafaro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;computedUserModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only significant difference is that a &lt;strong&gt;Structural Signal&lt;/strong&gt; is not notified when changes occur through a &lt;strong&gt;Deep Signal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It only detects changes when the &lt;strong&gt;parent Signal&lt;/strong&gt; is updated directly.&lt;/p&gt;

&lt;p&gt;By combining &lt;strong&gt;Structural Signals&lt;/strong&gt; and &lt;strong&gt;Deep Signals&lt;/strong&gt;, you can achieve more granular and intelligent control over updates, avoiding unnecessary triggers caused by new references that don’t actually change the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Davide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Passafaro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Structural Signal: returns the entire object&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userSnapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;structuralSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Deep Signal: accesses a specific nested property&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userCity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deepSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Effect that reacts only to full structural changes&lt;/span&gt;
&lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;🧱 Structural update:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;userSnapshot&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Effect that reacts only to changes in the city property&lt;/span&gt;
&lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;🌍 City changed:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;userCity&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Update only the city: triggers only the Deep Signal effect&lt;/span&gt;
&lt;span class="nx"&gt;userCity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Milan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Output:&lt;/span&gt;
&lt;span class="c1"&gt;// 🌍 City changed: Milan&lt;/span&gt;

&lt;span class="c1"&gt;// Structural update (new object): triggers both effects&lt;/span&gt;
&lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Davide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Passafaro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Turin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Output:&lt;/span&gt;
&lt;span class="c1"&gt;// 🌍 City changed: Turin&lt;/span&gt;
&lt;span class="c1"&gt;// 🧱 Structural update: { name: 'Davide', lastname: 'Passafaro', city: 'Turin' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, you can observe a precise behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you update only &lt;strong&gt;&lt;code&gt;userCity&lt;/code&gt;&lt;/strong&gt; through the &lt;strong&gt;Deep Signal&lt;/strong&gt;, only those listening to that property (like the first &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt;) will be notified.&lt;/li&gt;
&lt;li&gt;If you replace the entire &lt;strong&gt;&lt;code&gt;userModel&lt;/code&gt;&lt;/strong&gt; object, &lt;strong&gt;structural observers&lt;/strong&gt; (like the second &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt;) will also be notified.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The introduction of &lt;strong&gt;Deep Signals&lt;/strong&gt; and &lt;strong&gt;Structural Signals&lt;/strong&gt; is an exciting addition to the Angular ecosystem.&lt;/p&gt;

&lt;p&gt;Being able to &lt;strong&gt;update derived state within a Signal&lt;/strong&gt; directly is a major step forward for &lt;strong&gt;code readability&lt;/strong&gt;, &lt;strong&gt;maintainability&lt;/strong&gt;, and &lt;strong&gt;performance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That said, something is still missing.&lt;/p&gt;

&lt;p&gt;Currently, &lt;strong&gt;Deep Signals&lt;/strong&gt; only support nested properties at a single level of depth. It’s not yet possible to reactively access &lt;strong&gt;deeper properties&lt;/strong&gt; or &lt;strong&gt;state derived from more complex computations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These limitations don’t take away from the value of the new primitives, they’re just a clear &lt;strong&gt;signal&lt;/strong&gt; (badum-tss 🥁) of the direction Angular is heading. With each new release, it’s becoming more powerful and flexible.&lt;/p&gt;

&lt;p&gt;All that’s left for us is to wait, ready to play with the next innovations. 🤓&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful links for further reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/angular/angular/pull/62962/files#diff-a5dacbd9cf48a29ae38710189647532d1911644686978c693f1588ffc64613fa" rel="noopener noreferrer"&gt;Deep signal, deep magic — Angular PR #62962&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Thanks for reading! 🫶🏻
&lt;/h2&gt;

&lt;p&gt;If you enjoyed the read and found it useful, leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt;, or hit &lt;strong&gt;follow&lt;/strong&gt; to stay in the loop. I’ll appreciate it! 👏&lt;/p&gt;

&lt;p&gt;Don’t forget to share it with your community, tech friends, or anyone who might find it helpful! And &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;, let’s connect! 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Exploring Angular httpResource: a new approach to async data fetching</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Thu, 20 Mar 2025 11:16:31 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/exploring-angular-httpresource-a-new-approach-to-async-data-fetching-52mj</link>
      <guid>https://dev.to/davidepassafaro/exploring-angular-httpresource-a-new-approach-to-async-data-fetching-52mj</guid>
      <description>&lt;p&gt;In the past two years, Angular has embarked on a journey to revolutionize its reactive model, introducing signals as core primitives for synchronous reactivity within the framework. More recently, this journey has expanded into the realm of asynchronous reactivity with the new &lt;strong&gt;Resource API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With the latest updates, Angular has gone even further by introducing a specialized resource type: &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;. This addition extends the Resource API, offering a more efficient way to handle HTTP requests.&lt;/p&gt;

&lt;p&gt;In this article, I’ll explore how &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; works and how to use it in real-world scenarios, starting with a quick refresh of the &lt;strong&gt;Resource API&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Resource API
&lt;/h2&gt;

&lt;p&gt;The Angular &lt;strong&gt;Resource API&lt;/strong&gt; is designed to simplify asynchronous resource loading by leveraging signals.&lt;/p&gt;

&lt;p&gt;It offers a streamlined approach to managing data requests, tracking loading states, and automatically refreshing data when the signals on which the resource depends change.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use a Resource?
&lt;/h3&gt;

&lt;p&gt;To use a &lt;strong&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/strong&gt;, you can use the &lt;strong&gt;&lt;code&gt;resource()&lt;/code&gt;&lt;/strong&gt; function, where you define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;&lt;code&gt;request&lt;/code&gt; function&lt;/strong&gt; that returns the parameters for the async request;&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;&lt;code&gt;loader&lt;/code&gt; function&lt;/strong&gt; that fetches data based on the &lt;strong&gt;&lt;code&gt;request&lt;/code&gt;&lt;/strong&gt; parameters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a simplified example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A &lt;strong&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/strong&gt; automatically tracks the &lt;strong&gt;&lt;code&gt;request&lt;/code&gt;&lt;/strong&gt; parameters and, whenever they are updated, fetches new data using the &lt;strong&gt;&lt;code&gt;loader&lt;/code&gt;&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;Most importantly, it monitors the status of the data-fetching operation, tracking the &lt;strong&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/strong&gt;’s current &lt;strong&gt;value&lt;/strong&gt;, &lt;strong&gt;status&lt;/strong&gt;, and any &lt;strong&gt;errors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more details about the &lt;strong&gt;Resource API&lt;/strong&gt;, including its lifecycle, error handling, and how to consume a resource, check out my previous article:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/davidepassafaro" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F775852%2Fafd61a9c-ee2d-41c0-a227-551b790190e8.png" alt="davidepassafaro"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/davidepassafaro/angular-resource-and-rxresource-apis-what-you-need-to-know-5ce2" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Angular resource() and rxResource() APIs: what you need to know&lt;/h2&gt;
      &lt;h3&gt;Davide Passafaro ・ Jan 1 '25&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#angular&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#frontend&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;






&lt;p&gt;Now that we’ve had a good refresh on the &lt;strong&gt;Resource API&lt;/strong&gt;, let’s dive into the new &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;. 💪🏻&lt;/p&gt;

&lt;h2&gt;
  
  
  The httpResource
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; is a specialized type of &lt;strong&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/strong&gt; designed to handle &lt;strong&gt;HTTP requests&lt;/strong&gt; and expose all related request information via &lt;strong&gt;signals&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  httpResponse( ) function
&lt;/h3&gt;

&lt;p&gt;To create an &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; you can easily use the &lt;strong&gt;&lt;code&gt;httpResource()&lt;/code&gt;&lt;/strong&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpResourceRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./todo.model&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;staticHttpResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;reactiveHttpResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;configuredHttpResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HttpResourceRequest&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;reactiveConfiguredHttpResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HttpResourceRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; similar to a &lt;strong&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/strong&gt;, an &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; requires an injection context to be created. You can create one as a directive variable, instantiate it inside the constructor, or provide a specific injection context upon creation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;httpResource()&lt;/code&gt;&lt;/strong&gt; function requires only one parameter, which can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;&lt;code&gt;string&lt;/code&gt;&lt;/strong&gt;, representing the URL from which to fetch the data;&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;reactive function that returns a &lt;code&gt;string&lt;/code&gt;&lt;/strong&gt;, the resource will fetch the data from the new URL whenever it changes due to a signal update;&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;object of type &lt;code&gt;HttpResourceRequest&lt;/code&gt;&lt;/strong&gt;, which allows specifying additional details such as headers and request body;&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;reactive function that returns a &lt;code&gt;HttpResourceRequest&lt;/code&gt; object&lt;/strong&gt;, the resource will fetch the data with the new request parameters whenever this object changes due to a signal update.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This flexibility allows &lt;strong&gt;&lt;code&gt;httpResource()&lt;/code&gt;&lt;/strong&gt; to adapt to various application needs, simplifying asynchronous resource consumption in a declarative way.&lt;/p&gt;

&lt;p&gt;Under the hood, the provided parameter value is used to generate a function that creates an &lt;strong&gt;&lt;code&gt;HttpRequest&lt;/code&gt;&lt;/strong&gt;. This function is then passed to the basic &lt;strong&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/strong&gt; implementation as the &lt;strong&gt;&lt;code&gt;request&lt;/code&gt;&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;By providing reactive functions, &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; can track to signal changes, ensuring the &lt;strong&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/strong&gt; updates dynamically when dependencies change.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; you can find a detailed explanation of HttpResourceRequest below 👇🏻&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Configure the Resource with HttpResourceOptions
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;httpResource()&lt;/code&gt;&lt;/strong&gt; function accepts an optional second parameter of type &lt;strong&gt;&lt;code&gt;HttpResourceOptions&lt;/code&gt;&lt;/strong&gt;, allowing you to specify the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;defaultValue&lt;/code&gt;&lt;/strong&gt;: the value that the resource will take in &lt;strong&gt;Idle&lt;/strong&gt;, &lt;strong&gt;Loading&lt;/strong&gt;, or &lt;strong&gt;Error&lt;/strong&gt; states. If not specified, the resource will default to &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;parse&lt;/code&gt;&lt;/strong&gt;: a function that processes the raw response of the http request before assigning it to the &lt;strong&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/strong&gt; value. If not specified, TypeScript will infer the provided type through a type assertion.
It allows validation, transformation, or schema enforcement:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defaultUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isValidUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./user.utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;userResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;defaultUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isValidUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid user data received&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;toUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;injector&lt;/code&gt;&lt;/strong&gt;: overrides the &lt;strong&gt;&lt;code&gt;Injector&lt;/code&gt;&lt;/strong&gt; used by the &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; instance to destroy itself when the parent component or service is destroyed;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;equal&lt;/code&gt;&lt;/strong&gt;: equality function used to compare the response value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fetching data types other than JSON
&lt;/h3&gt;

&lt;p&gt;By default, an &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; assumes the response type is JSON.&lt;/p&gt;

&lt;p&gt;In order to request a different type of data, you can use specific variants of &lt;strong&gt;&lt;code&gt;httpResource()&lt;/code&gt;&lt;/strong&gt; function provided by &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;httpResource.text()&lt;/code&gt;&lt;/strong&gt;: to handle responses in plain text format;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;httpResource.blob()&lt;/code&gt;&lt;/strong&gt;: to handle binary data, such as images or files;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;httpResource.arrayBuffer()&lt;/code&gt;&lt;/strong&gt;: to handle raw binary data as &lt;strong&gt;&lt;code&gt;ArrayBuffer&lt;/code&gt;&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Fetching plain text&lt;/span&gt;
&lt;span class="nx"&gt;textResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/endpoint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Fetching binary data (e.g., image)&lt;/span&gt;
&lt;span class="nx"&gt;imageResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Fetching raw binary data as ArrayBuffer&lt;/span&gt;
&lt;span class="nx"&gt;arrayBufferResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  HttpClient integration and Interceptors support
&lt;/h3&gt;

&lt;p&gt;Under the hood, &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; leverages on the &lt;strong&gt;&lt;code&gt;HttpClient&lt;/code&gt;&lt;/strong&gt;, so to use it, you need to provide it to your component or service, usually via &lt;strong&gt;&lt;code&gt;provideHttpClient&lt;/code&gt;&lt;/strong&gt; or by importing &lt;strong&gt;&lt;code&gt;HttpClientModule&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This integration allows you to leverage any &lt;strong&gt;&lt;code&gt;HttpInterceptor&lt;/code&gt;&lt;/strong&gt; you have in place for request transformation, authentication handling, and error management. This way, you can seamlessly integrate &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; into your existing app while fully benefiting from your existing HTTP setup.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; the &lt;strong&gt;&lt;code&gt;HttpClient&lt;/code&gt;&lt;/strong&gt; implementation may be removed in future updates, but it’s likely that an alternative solution will be provided to ensure continued functionality. So, keep an eye on future updates! 🫣&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;p&gt;Theory is great, but it’s the practical implementation that truly matters.&lt;br&gt;
Let’s dive into some real-world examples using &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Forms and Search optimizations
&lt;/h3&gt;

&lt;p&gt;When building dynamic forms or search features, optimizing data requests is essential. One of the most common strategies is to &lt;strong&gt;reduce unnecessary API calls by controlling when and how requests are triggered&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is easily achievable by tracking input changes and applying techniques to ensure requests are only made when the user has stopped typing or when the input value actually changes.&lt;/p&gt;

&lt;p&gt;When dealing with &lt;strong&gt;&lt;code&gt;Observable&lt;/code&gt;&lt;/strong&gt;-based events, you can use operators like &lt;strong&gt;&lt;code&gt;debounceTime&lt;/code&gt;&lt;/strong&gt; to delay emissions until a specified time has passed without new values, or &lt;strong&gt;&lt;code&gt;distinctUntilChanged&lt;/code&gt;&lt;/strong&gt; to ensure only unique values are emitted.&lt;/p&gt;

&lt;p&gt;However, since signals do not rely on the concept of time like Observables, these strategies cannot be applied directly when using &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In order to work around this limitation, you can combine the power of signals and Observables by leveraging the &lt;strong&gt;&lt;code&gt;toObservable()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;toSignal()&lt;/code&gt;&lt;/strong&gt; functions provided by the &lt;strong&gt;&lt;code&gt;@angular/core/rxjs-interop&lt;/code&gt;&lt;/strong&gt; library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feq8uaokmvkb5ol10x0mk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feq8uaokmvkb5ol10x0mk.png" width="729" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This allows you to transform signals into Observables, enabling you to apply operators like &lt;strong&gt;&lt;code&gt;debounceTime&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;distinctUntilChanged&lt;/code&gt;&lt;/strong&gt;, and then convert the results back into a signal that you can use inside the &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;toObservable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toSignal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core/rxjs-interop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Convert the signal into an observable and apply debounceTime&lt;/span&gt;
&lt;span class="nx"&gt;idQuery$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;debounceTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Convert the observable back to a signal&lt;/span&gt;
&lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;idQuery$&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Use the query signal inside httpResource to fetch data&lt;/span&gt;
&lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="c1"&gt;// This is triggered only after the debounce&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; the &lt;strong&gt;&lt;code&gt;distinctUntilChanged&lt;/code&gt;&lt;/strong&gt; operator is not not necessary here because signals already avoid emitting unless their value actually changes. 🤓&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This hybrid approach gives you the flexibility to use time-based strategies while retaining the efficiency and simplicity of &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; and signals.&lt;/p&gt;

&lt;p&gt;Great! 🤩&lt;/p&gt;

&lt;h3&gt;
  
  
  Disabling the request without destroying the resource
&lt;/h3&gt;

&lt;p&gt;In some cases, you might want to disable the request without destroying the resource entirely. For instance, when data fetching should only happen after a specific user action, such as clicking a button.&lt;/p&gt;

&lt;p&gt;Instead of making the request immediately, you can conditionally enable it based on certain conditions, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;shouldFetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shouldFetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shouldFetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Custom condition&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;shouldFetchData&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; will only trigger the API request if the &lt;strong&gt;&lt;code&gt;shouldFetchData&lt;/code&gt;&lt;/strong&gt; signal is set to &lt;strong&gt;&lt;code&gt;true&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the condition is &lt;strong&gt;&lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;, the function returns &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;, preventing any API call from being made and resetting the values of the &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Returning &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt; is not the best, but it still gets the job done. 😅&lt;/p&gt;




&lt;h2&gt;
  
  
  HttpResourceRequest in detail
&lt;/h2&gt;

&lt;p&gt;Providing an &lt;strong&gt;&lt;code&gt;HttpResourceRequest&lt;/code&gt;&lt;/strong&gt; object to the &lt;strong&gt;&lt;code&gt;httpResource()&lt;/code&gt;&lt;/strong&gt; function allows you to specify additional details for customizing the HTTP request made by the &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;, enabling you to define the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;url&lt;/code&gt;&lt;/strong&gt;: the URL of the request. It should not include query parameters, which can be specified through the dedicated &lt;strong&gt;&lt;code&gt;params&lt;/code&gt;&lt;/strong&gt; property;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;method&lt;/code&gt;&lt;/strong&gt;: the HTTP method for the request. By default, the value is &lt;strong&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;body&lt;/code&gt;&lt;/strong&gt;: the body to include in the request. If no &lt;strong&gt;&lt;code&gt;Content-Type&lt;/code&gt;&lt;/strong&gt; header is specified, Angular will try to set one based on the &lt;strong&gt;&lt;code&gt;body&lt;/code&gt;&lt;/strong&gt; type.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;params&lt;/code&gt;&lt;/strong&gt;: query parameters to append to the URL, either as &lt;strong&gt;&lt;code&gt;HttpParams&lt;/code&gt;&lt;/strong&gt; or an object with key-value pairs, where values can be strings, numbers, booleans, or arrays of these types;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;headers&lt;/code&gt;&lt;/strong&gt;: headers to include with the request, either as &lt;strong&gt;&lt;code&gt;HttpHeaders&lt;/code&gt;&lt;/strong&gt; or a plain object with header names as keys and string or array values;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;context&lt;/code&gt;&lt;/strong&gt;: dictionary of key-value pairs to store additional context for the request, allowing it to carry custom metadata for handling or logging;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;reportProgress&lt;/code&gt;&lt;/strong&gt;: if set to &lt;strong&gt;&lt;code&gt;true&lt;/code&gt;&lt;/strong&gt;, enables progress events for the request.
These events are provided through the HttpResource.progress signal;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;withCredentials&lt;/code&gt;&lt;/strong&gt;: specifies whether to set the &lt;strong&gt;&lt;code&gt;withCredentials&lt;/code&gt;&lt;/strong&gt; flag on the outgoing request. When &lt;strong&gt;&lt;code&gt;true&lt;/code&gt;&lt;/strong&gt;, it allows the browser to send cookies and authentication information with the request;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;transferCache&lt;/code&gt;&lt;/strong&gt;: configures the server-side rendering transfer cache for the request. It can be a boolean or an object with an &lt;strong&gt;&lt;code&gt;includeHeaders&lt;/code&gt;&lt;/strong&gt; array that specifies which headers to include in the transfer cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Designed for fetching data only
&lt;/h3&gt;

&lt;p&gt;Even though you can define a different HTTP method using &lt;strong&gt;&lt;code&gt;HttpResourceRequest&lt;/code&gt;&lt;/strong&gt;, the new &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt; is primarily designed for fetching data, just like the fundamental &lt;strong&gt;Resource API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This flexibility is provided to allow the API to consume data that doesn’t necessarily align with standard HTTP specifications.&lt;/p&gt;

&lt;p&gt;However, it’s important to note that it is not safe to use an &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;, or any &lt;strong&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/strong&gt;, to save/delete data in such a way, as each update could abort previously initiated requests. As a result, operations like &lt;strong&gt;POST&lt;/strong&gt;, &lt;strong&gt;PUT&lt;/strong&gt;, or &lt;strong&gt;DELETE&lt;/strong&gt; may not be guaranteed to complete successfully.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thanks for reading! 🫶🏻
&lt;/h2&gt;

&lt;p&gt;I’m excited an honored to share that I’ve officially become a Google Developer Expert (&lt;strong&gt;GDE&lt;/strong&gt;) in &lt;strong&gt;Angular&lt;/strong&gt;! 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkrd4pktbfxf9k79pt7a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkrd4pktbfxf9k79pt7a.png" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you all for your support, I promise I’ll be writing more frequently, as this just got serious now. 😜🚀&lt;/p&gt;




&lt;p&gt;If you enjoyed the read and found it useful, leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt;, or hit &lt;strong&gt;follow&lt;/strong&gt; to stay in the loop. I’ll appreciate it! 👏&lt;/p&gt;

&lt;p&gt;Don’t forget to share it with your community, tech friends, or anyone who might find it helpful! And &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;, let’s connect! 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular resource() and rxResource() APIs: what you need to know</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Wed, 01 Jan 2025 15:00:00 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/angular-resource-and-rxresource-apis-what-you-need-to-know-5ce2</link>
      <guid>https://dev.to/davidepassafaro/angular-resource-and-rxresource-apis-what-you-need-to-know-5ce2</guid>
      <description>&lt;p&gt;The release of &lt;strong&gt;Angular v19&lt;/strong&gt;, just a few weeks ago, marks a significant milestone in the signal revolution within the framework, with the &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-signal-inputs-road-to-signal-components-32cl"&gt;Input&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-model-inputs-two-way-binding-inputs-with-signals-2nc7"&gt;Model&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-new-output-function-44f1"&gt;Output&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-signal-queries-simplifying-dom-querying-hmh"&gt;Signal Queries&lt;/a&gt;&lt;/strong&gt; APIs now officially promoted to stable.&lt;/p&gt;

&lt;p&gt;But that's not all! This major version also introduces powerful new tools designed to further advance the signal revolution: the new &lt;strong&gt;Resource API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As the name suggests, this new &lt;strong&gt;Resource API&lt;/strong&gt; is designed to simplify loading &lt;strong&gt;asynchronous resources&lt;/strong&gt; by harnessing the full power of signals!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT:&lt;/strong&gt; at the time of writing, the new &lt;strong&gt;Resource API&lt;/strong&gt; is still experimental. This means it may change before becoming stable, so use it at your own risk. 😅&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's dive into how it works and how it simplifies handling async resources!&lt;/p&gt;




&lt;h2&gt;
  
  
  The Resource API
&lt;/h2&gt;

&lt;p&gt;Most signal APIs are synchronous, but in real-world applications, it is essential to handle asynchronous resources, such as fetching data from a server or managing user interactions in real-time.&lt;/p&gt;

&lt;p&gt;This is where the new &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; API comes into play.&lt;/p&gt;

&lt;p&gt;Using a &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt;, you can easily consume an asynchronous resource via signals, allowing you to easily manage data fetching, handle loading states, and trigger a new fetch whenever the associated signal parameters change.&lt;/p&gt;

&lt;h3&gt;
  
  
  resource( ) function
&lt;/h3&gt;

&lt;p&gt;The easier way to create a &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; is by using the &lt;strong&gt;&lt;code&gt;resource()&lt;/code&gt;&lt;/strong&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function accepts a &lt;strong&gt;&lt;code&gt;ResourceOptions&lt;/code&gt;&lt;/strong&gt; configuration object as input, allowing you to specify the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;request&lt;/code&gt;&lt;/strong&gt;: a &lt;strong&gt;reactive function&lt;/strong&gt; that determines the parameters used to perform the request to the asynchronous resource;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;loader&lt;/code&gt;&lt;/strong&gt;: a loading function that returns a &lt;strong&gt;&lt;code&gt;Promise&lt;/code&gt;&lt;/strong&gt; of the resource's value, optionally based on the provided &lt;strong&gt;&lt;code&gt;request&lt;/code&gt;&lt;/strong&gt; parameters. This is the only &lt;strong&gt;required&lt;/strong&gt; property of &lt;strong&gt;&lt;code&gt;ResourceOptions&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;equal&lt;/code&gt;&lt;/strong&gt;: equality function used to compare the &lt;strong&gt;&lt;code&gt;loader&lt;/code&gt;&lt;/strong&gt;'s return value;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;injector&lt;/code&gt;&lt;/strong&gt;: overrides the &lt;strong&gt;&lt;code&gt;Injector&lt;/code&gt;&lt;/strong&gt; used by the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; instance to destroy itself when the parent component or service is destroyed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to these configurations, we can easily define an &lt;strong&gt;asynchronous dependency&lt;/strong&gt; that will always be consumed efficiently and kept up-to-date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource life cycle
&lt;/h3&gt;

&lt;p&gt;Once a &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; is created, the &lt;strong&gt;&lt;code&gt;loader&lt;/code&gt;&lt;/strong&gt; function is executed, then the resulting &lt;strong&gt;asynchronous request&lt;/strong&gt; starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever a signal that the &lt;strong&gt;&lt;code&gt;request&lt;/code&gt;&lt;/strong&gt; function depends on changes, the &lt;strong&gt;&lt;code&gt;request&lt;/code&gt;&lt;/strong&gt; function runs again, and if it returns new parameters, the &lt;strong&gt;&lt;code&gt;loader&lt;/code&gt;&lt;/strong&gt; function is triggered to fetch the updated resource's value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;

&lt;span class="c1"&gt;// After the fetch resolves&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 4 (which means "Resolved")&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { "id": 1 , ... }&lt;/span&gt;

&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Triggers a request, causing the loader function to run again&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;

&lt;span class="c1"&gt;// After the fetch resolves&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 4 (which means "Resolved")&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { "id": 2 , ... }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If no &lt;strong&gt;&lt;code&gt;request&lt;/code&gt;&lt;/strong&gt; function is provided, the &lt;strong&gt;&lt;code&gt;loader&lt;/code&gt;&lt;/strong&gt; function will run only once, unless the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; is reloaded using the &lt;strong&gt;&lt;code&gt;reload&lt;/code&gt;&lt;/strong&gt; method (more below).&lt;/p&gt;

&lt;p&gt;Finally, once the parent component or service is destroyed, the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; is also destroyed unless a specific injector has been provided.&lt;/p&gt;

&lt;p&gt;In such cases, the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; will remain active and be destroyed only when the provided &lt;strong&gt;&lt;code&gt;injector&lt;/code&gt;&lt;/strong&gt; itself is destroyed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aborting requests with abortSignal
&lt;/h3&gt;

&lt;p&gt;To optimize data fetching, a &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; can abort an outstanding requests if the &lt;strong&gt;&lt;code&gt;request()&lt;/code&gt;&lt;/strong&gt; computation changes while a previous value is still loading.&lt;/p&gt;

&lt;p&gt;To manage this, the &lt;strong&gt;&lt;code&gt;loader()&lt;/code&gt;&lt;/strong&gt; function provides an &lt;strong&gt;&lt;code&gt;abortSignal&lt;/code&gt;&lt;/strong&gt;, which you can pass to ongoing requests, such as &lt;strong&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/strong&gt;. The request listens for the &lt;strong&gt;&lt;code&gt;abortSignal&lt;/code&gt;&lt;/strong&gt; and cancels the operation if it's triggered, ensuring efficient resource management and preventing unnecessary network requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;abortSignal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;abortSignal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;

&lt;span class="c1"&gt;// Triggers a new request, causing the previous fetch to be aborted&lt;/span&gt;
&lt;span class="c1"&gt;// Then the loader function to run again generating a new fetch request&lt;/span&gt;
&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on this, it's recommended to use the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; API primarily for &lt;strong&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/strong&gt; requests, as they are typically safe to cancel without causing issues.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;UPDATE&lt;/code&gt;&lt;/strong&gt; requests, canceling might lead to unintended side effects, such as incomplete data submissions or updates. However, if you need similar functionality for these types of requests, you can use the &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt; method to safely manage the operations.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to consume a Resource
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; API provides several signal properties for its state, that you can easily use directly within your components or services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;value&lt;/code&gt;&lt;/strong&gt;: contains the current value of the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt;, or &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt; if no value is available. As a &lt;strong&gt;&lt;code&gt;WritableSignal&lt;/code&gt;&lt;/strong&gt;, it can be manually updated;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;status&lt;/code&gt;&lt;/strong&gt;: contains the current status of the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt;, indicating what the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; is doing and what can be expected from its &lt;strong&gt;&lt;code&gt;value&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;error&lt;/code&gt;&lt;/strong&gt;: if in the error state, it contains the most recent error raised during the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; load;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;isLoading&lt;/code&gt;&lt;/strong&gt;: indicates whether the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; is loading a new value or reloading the existing one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example of how to consume a &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; within a component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    @if (myResource.value()) {
      {{ myResource.value().title }}
    }

    &amp;lt;button (click)="fetchNext()"&amp;gt;Fetch next item&amp;lt;/button&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;fetchNext&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; is used to fetch data from an API based on the value of the &lt;strong&gt;&lt;code&gt;id&lt;/code&gt;&lt;/strong&gt; signal, which can be incremented by clicking a button.&lt;/p&gt;

&lt;p&gt;Whenever the user clicks the button, the &lt;strong&gt;&lt;code&gt;id&lt;/code&gt;&lt;/strong&gt; signal value changes, triggering the &lt;strong&gt;&lt;code&gt;loader&lt;/code&gt;&lt;/strong&gt; function to fetch a new item from the remote API.&lt;/p&gt;

&lt;p&gt;The UI automatically updates with the fetched data thanks to the signals properties exposed by the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; API.&lt;/p&gt;




&lt;h2&gt;
  
  
  Check the status of a Resource
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, the &lt;strong&gt;&lt;code&gt;status&lt;/code&gt;&lt;/strong&gt; signal provides information about the current state of the resource at any given moment.&lt;/p&gt;

&lt;p&gt;The possible values of the &lt;strong&gt;&lt;code&gt;status&lt;/code&gt;&lt;/strong&gt; signal are defined by the &lt;strong&gt;&lt;code&gt;ResourceStatus&lt;/code&gt;&lt;/strong&gt; enum. Here's a summary of these statuses and their corresponding values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Idle = &lt;strong&gt;&lt;code&gt;0&lt;/code&gt;&lt;/strong&gt;: the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; has no valid request and will not perform any loading. &lt;strong&gt;&lt;code&gt;value()&lt;/code&gt;&lt;/strong&gt; is &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Error = &lt;strong&gt;&lt;code&gt;1&lt;/code&gt;&lt;/strong&gt;: the loading has failed with an error. &lt;strong&gt;&lt;code&gt;value()&lt;/code&gt;&lt;/strong&gt; is &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Loading = &lt;strong&gt;&lt;code&gt;2&lt;/code&gt;&lt;/strong&gt;: the resource is currently loading a new value as a result of a change in its request. &lt;strong&gt;&lt;code&gt;value()&lt;/code&gt;&lt;/strong&gt; is &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Reloading = &lt;strong&gt;&lt;code&gt;3&lt;/code&gt;&lt;/strong&gt;: the resource is currently reloading a fresh value for the same request. &lt;strong&gt;&lt;code&gt;value()&lt;/code&gt;&lt;/strong&gt; will continue to return the previously fetched value until the reloading operation completes;&lt;/li&gt;
&lt;li&gt;Resolved = &lt;strong&gt;&lt;code&gt;4&lt;/code&gt;&lt;/strong&gt;: the loading is completed. &lt;strong&gt;&lt;code&gt;value()&lt;/code&gt;&lt;/strong&gt; contains the value returned from the loader data-fetching process;&lt;/li&gt;
&lt;li&gt;Local = &lt;strong&gt;&lt;code&gt;5&lt;/code&gt;&lt;/strong&gt;: the value was set locally via &lt;strong&gt;&lt;code&gt;set()&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;update()&lt;/code&gt;&lt;/strong&gt;. &lt;strong&gt;&lt;code&gt;value()&lt;/code&gt;&lt;/strong&gt; contains the value manually assigned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These statuses help track the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt;'s progress and facilitate better handling of asynchronous operations in your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  hasValue( ) function
&lt;/h3&gt;

&lt;p&gt;Given the complexity of these statuses, the &lt;strong&gt;Resource API&lt;/strong&gt; provides a &lt;strong&gt;&lt;code&gt;hasValue()&lt;/code&gt;&lt;/strong&gt; method, which returns a boolean based on the current status.&lt;/p&gt;

&lt;p&gt;This ensures accurate information about the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt;'s status, providing a more reliable way to handle asynchronous operations without relying on the value, which might be &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt; in certain states.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;hasValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ResourceStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Resolved&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ResourceStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Local&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ResourceStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reloading&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method is reactive, allowing you to consume and track it like a &lt;strong&gt;&lt;code&gt;signal&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  isLoading( ) function
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; API also provides an &lt;strong&gt;&lt;code&gt;isLoading&lt;/code&gt;&lt;/strong&gt; signal, which returns whether the resource is currently in the &lt;strong&gt;&lt;code&gt;Loading&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;Reloading&lt;/code&gt;&lt;/strong&gt; state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ResourceStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ResourceStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reloading&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;strong&gt;&lt;code&gt;isLoading&lt;/code&gt;&lt;/strong&gt; is a computed signal, it can be tracked reactively, allowing you to monitor the loading state in real-time using signals APIs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resource value as a WritableSignal
&lt;/h2&gt;

&lt;p&gt;The value signal provided by a &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; is a &lt;strong&gt;&lt;code&gt;WritableSignal&lt;/code&gt;&lt;/strong&gt;, which allows you to update it manually using the &lt;strong&gt;&lt;code&gt;set()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;update()&lt;/code&gt;&lt;/strong&gt; functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;

&lt;span class="c1"&gt;// After the fetch resolves&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 4 (which means "Resolved")&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { "id": 1 , ... }&lt;/span&gt;

&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { id: 2 }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 5 (which means "Local")&lt;/span&gt;

&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Davide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { id: 2, name: 'Davide' }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 5 (which means "Local")&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; as you can see, manually updating the &lt;strong&gt;&lt;code&gt;value&lt;/code&gt;&lt;/strong&gt; of the signal will also set the status to &lt;strong&gt;&lt;code&gt;5&lt;/code&gt;&lt;/strong&gt;, which means "&lt;strong&gt;Local&lt;/strong&gt;", to indicate that the value was set locally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The manually set value will persist until either a new value is set or a new request is performed, which will override it with a new value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;

&lt;span class="c1"&gt;// After the fetch resolves&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 4 (which means "Resolved")&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { "id": 1 , ... }&lt;/span&gt;

&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { id: 2 }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 5 (which means "Local")&lt;/span&gt;

&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Triggers a request, causing the loader function to run again&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;

&lt;span class="c1"&gt;// After the fetch resolves&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 4 (which means "Resolved")&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { "id": 3 , ... }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; the &lt;strong&gt;&lt;code&gt;value&lt;/code&gt;&lt;/strong&gt; signal of the &lt;strong&gt;Resource API&lt;/strong&gt; uses the same pattern of the new &lt;strong&gt;&lt;code&gt;LinkedSignal&lt;/code&gt;&lt;/strong&gt; API, but does not use it under the hood. 🤓&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Convenience wrappers methods
&lt;/h3&gt;

&lt;p&gt;To simplify the use of the &lt;strong&gt;&lt;code&gt;value&lt;/code&gt;&lt;/strong&gt; signal, the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; API provides convenience wrappers for the &lt;strong&gt;&lt;code&gt;set&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;update&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;code&gt;asReadonly&lt;/code&gt;&lt;/strong&gt; methods.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;asReadonly&lt;/code&gt;&lt;/strong&gt; method is particularly useful as it returns a read-only instance of the &lt;strong&gt;&lt;code&gt;value&lt;/code&gt;&lt;/strong&gt; signal, allowing access only for reading and preventing any accidental modifications.&lt;/p&gt;

&lt;p&gt;You can use this approach to create services that manage and track changes to resource values by exporting a read-only instance of the &lt;strong&gt;&lt;code&gt;value&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;myValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asReadonly&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Wrapper of `myResource.value.set()`&lt;/span&gt;
    &lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;addToValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addToValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Wrapper of `myResource.value.update()`&lt;/span&gt;
    &lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;addToValue&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage of the service in a component or other part of the application&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;myService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Property 'set' does not exist in type 'Signal'&lt;/span&gt;

&lt;span class="nx"&gt;myService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;myValue&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { id: 2 }&lt;/span&gt;

&lt;span class="nx"&gt;myService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addToValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Davide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;myValue&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { id: 2, name: 'Davide' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will prevent consumers from modifying the value, reducing the risk of unintended changes, improving consistency in complex data management.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reload or destroy a Resource
&lt;/h2&gt;

&lt;p&gt;When working with asynchronous resources, you may face scenarios where refreshing the data or destroy the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; becomes necessary.&lt;/p&gt;

&lt;p&gt;To handle these scenarios, the &lt;strong&gt;Resource API&lt;/strong&gt; provides two dedicated methods that offer efficient solutions for managing these actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  reload( ) function
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;reload()&lt;/code&gt;&lt;/strong&gt; method instructs the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; to re-execute the asynchronous request, ensuring it fetches the most up-to-date data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;

&lt;span class="c1"&gt;// After the fetch resolves&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 4 (which means "Resolved")&lt;/span&gt;

&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Returns true if a reload was initiated&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 3 (which means "Reloading")&lt;/span&gt;

&lt;span class="c1"&gt;// After the fetch resolves&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 5 (which means "Local")&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;&lt;code&gt;reload()&lt;/code&gt;&lt;/strong&gt; method returns &lt;strong&gt;&lt;code&gt;true&lt;/code&gt;&lt;/strong&gt; if a reload is successfully initiated.&lt;/p&gt;

&lt;p&gt;If a reload cannot be performed, either because it is unnecessary, such as when the status is already &lt;strong&gt;&lt;code&gt;Loading&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;Reloading&lt;/code&gt;&lt;/strong&gt;, or unsupported, like when the status is &lt;strong&gt;&lt;code&gt;Idle&lt;/code&gt;&lt;/strong&gt;, the method returns &lt;strong&gt;&lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  destroy( ) function
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;destroy()&lt;/code&gt;&lt;/strong&gt; method manually destroys the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt;, destroying any &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt; used to track request changes, canceling any pending requests, and setting the status to &lt;strong&gt;&lt;code&gt;Idle&lt;/code&gt;&lt;/strong&gt; while resetting the value to &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;

&lt;span class="c1"&gt;// After the fetch resolves&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 4 (which means "Resolved")&lt;/span&gt;

&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Returns true if a reload was initiated&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 1 (which means "Idle")&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; is destroyed, it will no longer respond to request changes or &lt;strong&gt;&lt;code&gt;reload()&lt;/code&gt;&lt;/strong&gt; operations.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; at this point, while the &lt;strong&gt;&lt;code&gt;value&lt;/code&gt;&lt;/strong&gt; signal remains writable, the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; will lose its intended purpose and no longer serves its function, becoming useless. 🙃&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  rxResource( ) function
&lt;/h2&gt;

&lt;p&gt;Like nearly all signal-based APIs introduced so far, the &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt; API also offers an interoperability utility for seamless integration with &lt;strong&gt;RxJS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of using the &lt;strong&gt;&lt;code&gt;resource()&lt;/code&gt;&lt;/strong&gt; method to create a Promise-based &lt;strong&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/strong&gt;, you can use the &lt;strong&gt;&lt;code&gt;rxResource()&lt;/code&gt;&lt;/strong&gt; method to use &lt;strong&gt;Observables&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rxResource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core/rxjs-interop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fromFetch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs/fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/todos/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rxResource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fromFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOURCE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 2 (which means "Loading")&lt;/span&gt;

&lt;span class="c1"&gt;// After the fetch resolves&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: 4 (which means "Resolved")&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Prints: { "id": 1 , ... }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; the &lt;strong&gt;&lt;code&gt;rxResource()&lt;/code&gt;&lt;/strong&gt; method is in fact exposed by the &lt;strong&gt;&lt;code&gt;rxjs-interop&lt;/code&gt;&lt;/strong&gt; package.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;strong&gt;Observable&lt;/strong&gt; produced by the &lt;strong&gt;&lt;code&gt;loader()&lt;/code&gt;&lt;/strong&gt; function will consider only the first emitted value, ignoring subsequent emissions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thanks for reading so far 🙏
&lt;/h2&gt;

&lt;p&gt;Thank you all for following me throughout this wonderful 2024. 🫶🏻&lt;/p&gt;

&lt;p&gt;It has been a year full of challenges, but also very rewarding. I have big plans for 2025 and I can't wait to start working on them. 🤩&lt;/p&gt;

&lt;p&gt;I’d like to have your feedback so please leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt; or &lt;strong&gt;follow&lt;/strong&gt;. 👏&lt;/p&gt;

&lt;p&gt;Then, if you really liked it, &lt;strong&gt;share it&lt;/strong&gt; among your community, tech bros and whoever you want. And don’t forget to &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;. 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular Forms new unified control state change events</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Mon, 10 Jun 2024 15:18:49 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/angular-forms-new-unified-control-state-change-events-2ndf</link>
      <guid>https://dev.to/davidepassafaro/angular-forms-new-unified-control-state-change-events-2ndf</guid>
      <description>&lt;p&gt;The release of &lt;strong&gt;Angular v18&lt;/strong&gt; brought a bunch of exciting new features and improvements to the framework.&lt;/p&gt;

&lt;p&gt;One of these features is particularly promising, as it introduces a new capability within the &lt;strong&gt;Angular Forms&lt;/strong&gt; library, by enhancing the &lt;strong&gt;&lt;code&gt;AbstractControl&lt;/code&gt;&lt;/strong&gt; class with unified control state change events.&lt;/p&gt;

&lt;p&gt;As usual in my articles, before delving into the main topic, let's first review some fundamentals. This will help you better grasp the upcoming contents.&lt;/p&gt;




&lt;h2&gt;
  
  
  Angular Reactive Forms: the fundamentals
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Angular Reactive Forms&lt;/strong&gt; offer a model-driven approach to handling form inputs, providing synchronous access to the data model, powerful tools for inputs validation and change tracking through &lt;strong&gt;&lt;code&gt;Observables&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Reactive Forms&lt;/strong&gt; data model is composed using the following classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;FormControl&lt;/code&gt;&lt;/strong&gt;: represents a single form input, its value is a primitive;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;FormGroup&lt;/code&gt;&lt;/strong&gt;: represents a group of &lt;strong&gt;&lt;code&gt;FormControl&lt;/code&gt;&lt;/strong&gt;, its value is an object;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;FormArray&lt;/code&gt;&lt;/strong&gt;: represents a list of &lt;strong&gt;&lt;code&gt;FormControl&lt;/code&gt;&lt;/strong&gt;, its value is an array.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A common example of form can be represented by a &lt;strong&gt;&lt;code&gt;FormGroup&lt;/code&gt;&lt;/strong&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FormArray&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/forms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;articleForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new FormControl(''),&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormArray&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; there is also the &lt;strong&gt;&lt;code&gt;FormRecord&lt;/code&gt;&lt;/strong&gt; class, an extension of the &lt;strong&gt;&lt;code&gt;FormGroup&lt;/code&gt;&lt;/strong&gt; class, which allows you to dynamically create a group of &lt;strong&gt;&lt;code&gt;FormControl&lt;/code&gt;&lt;/strong&gt; instances.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All these classes, hereafter referred to just as &lt;strong&gt;controls&lt;/strong&gt;, are derived from the &lt;strong&gt;&lt;code&gt;AbstractControl&lt;/code&gt;&lt;/strong&gt; class, and thus share common properties and methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Template binding
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Angular Reactive Forms&lt;/strong&gt; model-driven approach is powered by various directives provided by the library itself, which facilitate the integration of form controls with HTML elements.&lt;/p&gt;

&lt;p&gt;Let's take the following &lt;strong&gt;&lt;code&gt;FormGroup&lt;/code&gt;&lt;/strong&gt; as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;articleForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormArray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can easily bind it to the template using the provided directives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;[formGroup]=&lt;/span&gt;&lt;span class="s"&gt;"articleForm"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;formGroupName=&lt;/span&gt;&lt;span class="s"&gt;"author"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;formControlName=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;formArrayName=&lt;/span&gt;&lt;span class="s"&gt;"tags"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;*ngFor=&lt;/span&gt;&lt;span class="s"&gt;"let tag of tags.controls; index as i"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;[formControlName]=&lt;/span&gt;&lt;span class="s"&gt;"i"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is important to remember, without delving into an exhaustive but out-of-scope explanation, is that the &lt;strong&gt;&lt;code&gt;FormGroupDirective&lt;/code&gt;&lt;/strong&gt; allows us to easily create a button to &lt;strong&gt;reset&lt;/strong&gt; the form and a button to &lt;strong&gt;submit&lt;/strong&gt; its value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;[formGroup]=&lt;/span&gt;&lt;span class="s"&gt;"articleForm"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- form template --&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"reset"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Clear&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;&lt;code&gt;FormGroupDirective&lt;/code&gt;&lt;/strong&gt; intercepts the click events emitted by these buttons to trigger the control's &lt;strong&gt;&lt;code&gt;reset()&lt;/code&gt;&lt;/strong&gt; function, which resets the control to its initial value, and the directive's &lt;strong&gt;&lt;code&gt;ngSubmit&lt;/code&gt;&lt;/strong&gt; output event.&lt;/p&gt;

&lt;h3&gt;
  
  
  Listening for value changes
&lt;/h3&gt;

&lt;p&gt;In order to listen for value changes to perform custom operations, you can subscribe to the &lt;strong&gt;&lt;code&gt;valueChanges&lt;/code&gt;&lt;/strong&gt; observable of the control you want to track:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueChanges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New value:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Disabled controls
&lt;/h3&gt;

&lt;p&gt;Each control can be set to &lt;strong&gt;disabled&lt;/strong&gt;, preventing users from editing its value. This mimics the behavior of the HTML &lt;strong&gt;&lt;code&gt;disabled&lt;/code&gt;&lt;/strong&gt; attribute.&lt;/p&gt;

&lt;p&gt;To accomplish this, you can either create a control as &lt;strong&gt;disabled&lt;/strong&gt;, or use the &lt;strong&gt;&lt;code&gt;disable()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;enable()&lt;/code&gt;&lt;/strong&gt; and functions to toggle this status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FormControl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/forms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myControl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// true, false&lt;/span&gt;

&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// false, true&lt;/span&gt;

&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// true, false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can notice in the example above, the &lt;strong&gt;&lt;code&gt;AbstractControl&lt;/code&gt;&lt;/strong&gt; class provides two dedicated properties to describe this status: &lt;strong&gt;&lt;code&gt;disabled&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Validators
&lt;/h3&gt;

&lt;p&gt;To enforce specific rules and ensure that your controls meet certain criteria, you can also specify some validation rules, or &lt;strong&gt;validators&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Validators can be &lt;strong&gt;synchronous&lt;/strong&gt;, such as &lt;strong&gt;&lt;code&gt;required&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;minLength&lt;/code&gt;&lt;/strong&gt;, or &lt;strong&gt;asynchronous&lt;/strong&gt;, to handle validation that depends on external resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/forms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyCustomAsyncValidators&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-custom-async-validators.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFormControl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;asyncValidators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;MyCustomAsyncValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on these rules, the &lt;strong&gt;&lt;code&gt;AbstractControl&lt;/code&gt;&lt;/strong&gt; class provides also some properties that describe the status of the validity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;valid&lt;/code&gt;&lt;/strong&gt;: a boolean indicating whether the control value passed all of its validation rules tests;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;invalid&lt;/code&gt;&lt;/strong&gt;: a boolean indicating whether the control value passed all of its validation rules tests; It is the opposite of the &lt;strong&gt;&lt;code&gt;valid&lt;/code&gt;&lt;/strong&gt; property;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;pending&lt;/code&gt;&lt;/strong&gt;: a boolean indicating whether the control value is in the process of conducting a validation check.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FormControlStatus
&lt;/h2&gt;

&lt;p&gt;Both the &lt;strong&gt;disabled&lt;/strong&gt; status and the &lt;strong&gt;validation&lt;/strong&gt; status are interconnected.&lt;br&gt;
In fact, they are derived by the &lt;strong&gt;&lt;code&gt;status&lt;/code&gt;&lt;/strong&gt; property, which is typed as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FormControlStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;VALID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INVALID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PENDING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DISABLED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;valid&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;invalid&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;pending&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;disabled&lt;/code&gt;&lt;/strong&gt; properties are indeed just getters derived from the &lt;strong&gt;&lt;code&gt;status&lt;/code&gt;&lt;/strong&gt; property 🤓&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Pristine and Touched
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;AbstractControl&lt;/code&gt;&lt;/strong&gt; class provides also several properties that describe how the user has interacted with the form:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;pristine&lt;/code&gt;&lt;/strong&gt;: a boolean indicating whether the control is pristine, meaning it has &lt;strong&gt;not yet been modified&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dirty&lt;/code&gt;&lt;/strong&gt;: boolean indicating whether the control &lt;strong&gt;has been modified&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;untouched&lt;/code&gt;&lt;/strong&gt;: a boolean indicating whether the control has &lt;strong&gt;not yet been touched&lt;/strong&gt;, meaning that it has not been interacted with yet;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;touched&lt;/code&gt;&lt;/strong&gt;: a boolean indicating whether the control &lt;strong&gt;has been touched&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Now that we've revisited some of the fundamentals of &lt;strong&gt;Angular Reactive Forms&lt;/strong&gt;, it's finally time to introduce the main topic of this article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4bsgb8lt524s29qyulj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4bsgb8lt524s29qyulj.png" width="600" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  New unified control state change events
&lt;/h2&gt;

&lt;p&gt;Starting from Angular v18, the &lt;strong&gt;&lt;code&gt;AbstractControl&lt;/code&gt;&lt;/strong&gt; class now exposes a new &lt;strong&gt;&lt;code&gt;events&lt;/code&gt;&lt;/strong&gt; observable to track all control state change events.&lt;/p&gt;

&lt;p&gt;Thanks to this, you can now monitor &lt;strong&gt;&lt;code&gt;FormControl&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;FormGroup&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;FormArray&lt;/code&gt;&lt;/strong&gt; classes through the following events: &lt;strong&gt;&lt;code&gt;PristineEvent&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;PristineEvent&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;StatusEvent&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;TouchedEvent&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;PristineChangeEvent&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pristine:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pristine&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;ValueChangeEvent&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Value:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;StatusChangeEvent&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Status:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;TouchedChangeEvent&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Touched:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;touched&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These capabilities are very powerful, especially because, apart from the &lt;strong&gt;&lt;code&gt;valueChange&lt;/code&gt;&lt;/strong&gt;, it was previously not easy to properly track the state changes.&lt;/p&gt;

&lt;p&gt;Additionally to this, the &lt;strong&gt;&lt;code&gt;FormGroup&lt;/code&gt;&lt;/strong&gt; class can also emit two additional events through the &lt;strong&gt;&lt;code&gt;events&lt;/code&gt;&lt;/strong&gt; observable: &lt;strong&gt;&lt;code&gt;FormSubmittedEvent&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;FormResetEvent&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;FormSubmittedEvent&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Submit:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;myControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;FormResetEvent&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Reset:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both the &lt;strong&gt;&lt;code&gt;FormSubmittedEvent&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;FormResetEvent&lt;/code&gt;&lt;/strong&gt; are inherited by the &lt;strong&gt;&lt;code&gt;FormGroupDirective&lt;/code&gt;&lt;/strong&gt; and are, in fact, emitted only by the directive itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional insights
&lt;/h3&gt;

&lt;p&gt;Thanks to this new addition, the following &lt;strong&gt;&lt;code&gt;AbstractControl&lt;/code&gt;&lt;/strong&gt; methods have been updated to support the &lt;strong&gt;&lt;code&gt;emitEvent&lt;/code&gt;&lt;/strong&gt; parameter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;markAsPristine()&lt;/code&gt;&lt;/strong&gt;: marks the control as &lt;strong&gt;&lt;code&gt;pristine&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;markAsDirty()&lt;/code&gt;&lt;/strong&gt;: marks the control as &lt;strong&gt;&lt;code&gt;dirty&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;markAsTouched()&lt;/code&gt;&lt;/strong&gt;: marks the control as &lt;strong&gt;&lt;code&gt;touched&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;markAsUntouched()&lt;/code&gt;&lt;/strong&gt;: marks the control as &lt;strong&gt;&lt;code&gt;untouched&lt;/code&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;markAllAsTouched()&lt;/code&gt;&lt;/strong&gt;: marks the control and its descendant as &lt;strong&gt;&lt;code&gt;touched&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Thanks for reading so far 🙏
&lt;/h2&gt;

&lt;p&gt;I’d like to have your feedback so please leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt; or &lt;strong&gt;follow&lt;/strong&gt;. 👏&lt;/p&gt;

&lt;p&gt;Then, if you really liked it, &lt;strong&gt;share it&lt;/strong&gt; among your community, tech bros and whoever you want. And don’t forget to &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;. 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular fallback content in ng-content</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Wed, 08 May 2024 17:54:25 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/angular-fallback-content-in-ng-content-5d7m</link>
      <guid>https://dev.to/davidepassafaro/angular-fallback-content-in-ng-content-5d7m</guid>
      <description>&lt;p&gt;&lt;strong&gt;Angular v18&lt;/strong&gt; recently introduced a new feature to easily define a fallback content in &lt;strong&gt;&lt;code&gt;ng-content&lt;/code&gt;&lt;/strong&gt; elements. In this article, I will discuss about it.&lt;/p&gt;

&lt;p&gt;However, before diving into it, I will also explore how it was already possible to achieve the same result in &lt;strong&gt;Angular v17 or earlier versions&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;When building flexible and reusable UI components, content projection stands as a fundamental tool at your disposal. It is a pattern in which you insert, or &lt;strong&gt;project&lt;/strong&gt;, the content you want to use inside another component.&lt;/p&gt;

&lt;p&gt;When configuring a component, defining a &lt;strong&gt;fallback content&lt;/strong&gt; can be useful to ensure something is displayed if no content is provided.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define fallback content in ng-content elements
&lt;/h2&gt;

&lt;p&gt;Up until &lt;strong&gt;Angular v18&lt;/strong&gt;, there was not a built-in support to fallback content for &lt;strong&gt;&lt;code&gt;ng-content&lt;/code&gt;&lt;/strong&gt;. However, this didn’t imply there was no workaround.&lt;/p&gt;

&lt;p&gt;Let’s take a look at one of the potential implementation strategies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    @if(!hasContent()){
      &amp;lt;div&amp;gt; Default content &amp;lt;/div&amp;gt;
    }

    &amp;lt;div #wrapper&amp;gt;
      &amp;lt;ng-content&amp;gt;&amp;lt;/ng-content&amp;gt;
    &amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;wrapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wrapper&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;hasContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea behind it is to wrap the &lt;strong&gt;&lt;code&gt;ng-content&lt;/code&gt;&lt;/strong&gt; within an element, and utilize the &lt;strong&gt;&lt;code&gt;viewChild&lt;/code&gt;&lt;/strong&gt; API to determine whether there is projected content or not.&lt;/p&gt;

&lt;p&gt;Then, based on that, the fallback content is displayed using the &lt;strong&gt;&lt;code&gt;@if&lt;/code&gt;&lt;/strong&gt; API provided by the &lt;a href="https://dev.to/davidepassafaro/angular-control-flow-the-complete-guide-1pan"&gt;new control flow&lt;/a&gt;, or the &lt;strong&gt;&lt;code&gt;ngIf&lt;/code&gt;&lt;/strong&gt; directive.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; in older versions of &lt;strong&gt;Angular&lt;/strong&gt; you may need to refactor this a bit, but I hope the concept of this strategy is clear. If not please feel free to contact me 🫶🏻&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Angular v18: fallback content in ng-content
&lt;/h2&gt;

&lt;p&gt;Starting from &lt;strong&gt;Angular v18&lt;/strong&gt;, implementing a &lt;strong&gt;fallback content&lt;/strong&gt; in &lt;strong&gt;&lt;code&gt;ng-content&lt;/code&gt;&lt;/strong&gt; elements is extremely easier.&lt;/p&gt;

&lt;p&gt;You just need to put the &lt;strong&gt;fallback content&lt;/strong&gt; inside the &lt;strong&gt;&lt;code&gt;ng-content&lt;/code&gt;&lt;/strong&gt; tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;ng-content select="header"&amp;gt; Default header &amp;lt;/ng-content&amp;gt;

    &amp;lt;ng-content&amp;gt; Default main content &amp;lt;/ng-content&amp;gt;

    &amp;lt;ng-content select="footer"&amp;gt; Default footer &amp;lt;/ng-content&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this new feature allows you to easily define a dedicated &lt;strong&gt;fallback content&lt;/strong&gt; for each &lt;strong&gt;&lt;code&gt;ng-content&lt;/code&gt;&lt;/strong&gt; element in your component.&lt;/p&gt;

&lt;p&gt;So, considering the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;my-component&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt; New footer &lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/my-component&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting template will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;Default header

Default main content

&lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt; New footer &lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; before &lt;strong&gt;Angular v18&lt;/strong&gt;, this would result in an error being thrown ❌&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0uua8521skf73qjxfvq.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0uua8521skf73qjxfvq.jpeg" alt="TLDR: is this a good summary? 🤭" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Fallback content strategies limitations
&lt;/h2&gt;

&lt;p&gt;It is important to highlight that both strategies share the same limitation: &lt;strong&gt;Angular content projection is evaluated on component creation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This means that if you render the projected content conditionally, for example using an &lt;strong&gt;&lt;code&gt;@if&lt;/code&gt;&lt;/strong&gt; condition or the &lt;strong&gt;&lt;code&gt;ngIf&lt;/code&gt;&lt;/strong&gt; directive, the fallback content will not be displayed, even if the associated condition is set to &lt;strong&gt;&lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This limitation can be easily overcome, with different solutions depending on the specific use case you might have, but it’s important to remember about it when implementing the strategies I’ve presented.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thanks for reading so far 🙏
&lt;/h2&gt;

&lt;p&gt;I’d like to have your feedback so please leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt; or &lt;strong&gt;follow&lt;/strong&gt;. 👏&lt;/p&gt;

&lt;p&gt;Then, if you really liked it, &lt;strong&gt;share it&lt;/strong&gt; among your community, tech bros and whoever you want. And don’t forget to &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;. 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Redirecting Guards and Resolvers in Angular v18 with RedirectCommand</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Mon, 29 Apr 2024 07:00:00 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/advanced-angular-navigation-redirect-guards-and-resolvers-in-angular-v18-15ne</link>
      <guid>https://dev.to/davidepassafaro/advanced-angular-navigation-redirect-guards-and-resolvers-in-angular-v18-15ne</guid>
      <description>&lt;p&gt;In the modern era of web development, creating dynamic and interactive applications has become the norm. Implementing features that are exclusive to certain users, or available under specific conditions, can be a very complex challenge.&lt;/p&gt;

&lt;p&gt;For this reason, &lt;strong&gt;Angular&lt;/strong&gt; offers a routing system based on &lt;strong&gt;Routes&lt;/strong&gt;, rules and components, enabling you to can easily design your applications.&lt;/p&gt;

&lt;p&gt;In this article, I will discuss about safeguarding &lt;strong&gt;Routes&lt;/strong&gt; redirecting the user elsewhere, using also a new feature introduced in &lt;strong&gt;Angular v18&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But before we proceed, let's have a brief review about &lt;strong&gt;Angular Router&lt;/strong&gt;…&lt;/p&gt;




&lt;h2&gt;
  
  
  Angular Router Guards and Resolvers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Angular Router&lt;/strong&gt; library allows you to manage navigation within your Angular application, defining a list of &lt;strong&gt;Routes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each &lt;strong&gt;Route&lt;/strong&gt; is defined by a series of information, such as the path to access it, the Angular component to load, &lt;strong&gt;child Routes&lt;/strong&gt; and much more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyFeatureComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyFeatureGuard&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyFeatureComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;canActivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyFeatureGuard&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-feature-id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can protect one or more &lt;strong&gt;Routes&lt;/strong&gt;, restricting the access or the exit, based on certain conditions, using functions called &lt;strong&gt;Guards&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myRoute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;canMatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;canMatch&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="nx"&gt;canActivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;canActivate&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="nx"&gt;canActivateChild&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;canActivateChild&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="nx"&gt;canDeactivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;canDeactivate&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are four types of Angular &lt;strong&gt;Guards&lt;/strong&gt;, each with a different role:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;canMatch&lt;/code&gt;&lt;/strong&gt;: used to verify that a Route can be loaded. You can define multiple Routes for a single path and use this guard to select only one based on certain conditions;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;canActivate&lt;/code&gt;&lt;/strong&gt;: used to determine whether a user can activate a particular Route. For example, you can use it to control access to pages reserved only for certain users;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;canActivateChild&lt;/code&gt;&lt;/strong&gt;: similar to &lt;strong&gt;&lt;code&gt;canActivate&lt;/code&gt;&lt;/strong&gt;, but it controls also the access to child Routes of a main Route. It runs on every navigation towards a child Route, even if it started from another child Route;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;canDeactivate&lt;/code&gt;&lt;/strong&gt;: used to verify whether a user can exit a given Route. For example, you can use it to ask for confirmation before leaving a page.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; originally, &lt;strong&gt;Guards&lt;/strong&gt; were implemented as &lt;strong&gt;Injectable services&lt;/strong&gt;. Following the introduction of the &lt;strong&gt;&lt;code&gt;inject()&lt;/code&gt;&lt;/strong&gt; function, it was possible to define them as functions. As a result, &lt;strong&gt;Injectable Guards are currently deprecated&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6w4zgn7crd7qbtumvipz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6w4zgn7crd7qbtumvipz.png" alt="Order of execution of the **Guards** during navigation" width="800" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Furthermore, you can use &lt;strong&gt;Resolver&lt;/strong&gt; functions to prepare data for a &lt;strong&gt;Route&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myRoute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getUserInfo&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getUserConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;strong&gt;Resolvers&lt;/strong&gt; is a great approach to ensure the presence of data before accessing a &lt;strong&gt;Route&lt;/strong&gt;, avoiding to deal with missing data in a page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frr8avp8sajtk4queqp2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frr8avp8sajtk4queqp2p.png" alt="Order of execution of **Resolvers** during navigation" width="800" height="167"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Now that I covered the basics, let's see how to protect your &lt;strong&gt;Routes&lt;/strong&gt; by redirecting users elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Guards and Resolvers to redirect navigation
&lt;/h2&gt;

&lt;p&gt;Angular Guards allow you to prevent access or exit to one or more &lt;strong&gt;Routes&lt;/strong&gt;, blocking navigation.&lt;/p&gt;

&lt;p&gt;However, to ensure a smoother user experience, it is often preferable to redirect the user to another &lt;strong&gt;Route&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;strong&gt;Guards&lt;/strong&gt;, we can achieve this very easily, starting a new navigation before blocking the current one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/my-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;canActivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-other-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can achieve a similar result using the &lt;strong&gt;Resolvers&lt;/strong&gt;, starting a new navigation inside them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myRoute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-other-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Redirect with UrlTree
&lt;/h3&gt;

&lt;p&gt;Alternatively, you can redirect navigation by having &lt;strong&gt;Guards&lt;/strong&gt; and &lt;strong&gt;Resolvers&lt;/strong&gt; return a &lt;strong&gt;&lt;code&gt;UrlTree&lt;/code&gt;&lt;/strong&gt; representing the new &lt;strong&gt;Route&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UrlTree&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/my-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;canActivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;urlTree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UrlTree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-other-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;urlTree&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this technique does not allow you to redirect navigation using &lt;strong&gt;&lt;code&gt;NavigationExtras&lt;/code&gt;&lt;/strong&gt;, as allowed by the previous technique:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;canActivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-other-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;skipLocationChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Redirect with RedirectCommand
&lt;/h3&gt;

&lt;p&gt;To overcome this, &lt;strong&gt;Angular v18&lt;/strong&gt; introduces a new &lt;strong&gt;&lt;code&gt;RedirectCommand&lt;/code&gt;&lt;/strong&gt; class capable of handling &lt;strong&gt;&lt;code&gt;NavigationExtras&lt;/code&gt;&lt;/strong&gt;, enabling you to redirect navigation in &lt;strong&gt;Guards&lt;/strong&gt; and &lt;strong&gt;Resolvers&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RedirectCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UrlTree&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/my-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;canActivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;urlTree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UrlTree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-other-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RedirectCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;urlTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;skipLocationChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The introduction of this new &lt;strong&gt;&lt;code&gt;RedirectCommand&lt;/code&gt;&lt;/strong&gt; class ensures great maintainability for &lt;strong&gt;Guards&lt;/strong&gt; and &lt;strong&gt;Resolvers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0yagno9iolft4h8mupjt.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0yagno9iolft4h8mupjt.jpeg" alt="New ** raw `RedirectCommand` endraw ** class introduction" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having been designed specifically for these use cases, it can be easily extended to adapt to any necessary new parameters in the future.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thanks for reading so far 🙏
&lt;/h2&gt;

&lt;p&gt;I’d like to have your feedback so please leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt; or &lt;strong&gt;follow&lt;/strong&gt;. 👏&lt;/p&gt;

&lt;p&gt;Then, if you really liked it, &lt;strong&gt;share it&lt;/strong&gt; among your community, tech bros and whoever you want. And don’t forget to &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;. 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular new output() function</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Wed, 24 Apr 2024 07:00:00 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/angular-new-output-function-44f1</link>
      <guid>https://dev.to/davidepassafaro/angular-new-output-function-44f1</guid>
      <description>&lt;p&gt;During latest months, &lt;strong&gt;Angular v17&lt;/strong&gt; has introduced a set of new function-based APIs focused on enhance Signal integration within components and directives. This includes &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-signal-inputs-road-to-signal-components-32cl"&gt;Signal Inputs&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-model-inputs-two-way-binding-inputs-with-signals-2nc7"&gt;Model Inputs&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-signal-queries-simplifying-dom-querying-hmh"&gt;Signal Queries&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Considering the full picture, we are only missing one core API to conclude this journey, and this article is dedicated to precisely that: &lt;strong&gt;Angular v17.3.0&lt;/strong&gt; latest addition, the new &lt;strong&gt;&lt;code&gt;output()&lt;/code&gt;&lt;/strong&gt; function.&lt;/p&gt;




&lt;h2&gt;
  
  
  The new &lt;strong&gt;&lt;code&gt;output()&lt;/code&gt;&lt;/strong&gt; API
&lt;/h2&gt;

&lt;p&gt;Similar to the function-based APIs introduced so far, you now have a brand new &lt;strong&gt;&lt;code&gt;output()&lt;/code&gt;&lt;/strong&gt; function designed to replace the &lt;strong&gt;@Output&lt;/strong&gt; decorator.&lt;/p&gt;

&lt;p&gt;To declare an output, you can now use the &lt;strong&gt;&lt;code&gt;output()&lt;/code&gt;&lt;/strong&gt; function when we declare a property of a component or directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OutputEmitterRef&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;button (click)="emitClick($event)"&amp;gt;Click here&amp;lt;/button&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;buttonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aliasClick&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;emitClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buttonClick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see from the example, this API also supports the &lt;strong&gt;&lt;code&gt;alias&lt;/code&gt;&lt;/strong&gt; property and exposes the &lt;strong&gt;&lt;code&gt;emit()&lt;/code&gt;&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;Furthermore, you can listen for the output event in the parent components, using Angular event binding syntax in the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;my-component&lt;/span&gt;
  &lt;span class="na"&gt;(buttonClick)=&lt;/span&gt;&lt;span class="s"&gt;"myFunction($event)"&lt;/span&gt;
  &lt;span class="na"&gt;(aliasClick)=&lt;/span&gt;&lt;span class="s"&gt;"myFunction($event)"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, everything works almost identically to &lt;strong&gt;@Output&lt;/strong&gt; decorator-based outputs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdqka7widqqcnxdhp2ovk.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdqka7widqqcnxdhp2ovk.jpeg" alt="@Output is replaced by the new ** raw `output()` endraw ** function" width="800" height="787"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s now move on to the &lt;strong&gt;&lt;code&gt;subscribe()&lt;/code&gt;&lt;/strong&gt; function, which brings some changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to subscribe to outputs programmatically
&lt;/h3&gt;

&lt;p&gt;Using the &lt;strong&gt;&lt;code&gt;output()&lt;/code&gt;&lt;/strong&gt; function you get an instance of type &lt;strong&gt;OutputEmitterRef&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;buttonClick&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OutputEmitterRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to the already mentioned &lt;strong&gt;&lt;code&gt;emit()&lt;/code&gt;&lt;/strong&gt; method, which has remained unchanged on the surface, this class also exposes a &lt;strong&gt;&lt;code&gt;subscribe()&lt;/code&gt;&lt;/strong&gt; method to listen to the event programmatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-parent-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;my-component /&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyParentComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;myComponentRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;myComponentRef&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;myOutput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Manual subscription:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The subscription generated by this class is not based on &lt;strong&gt;RxJs&lt;/strong&gt;, so you can’t use the &lt;strong&gt;&lt;code&gt;pipe()&lt;/code&gt;&lt;/strong&gt; function and operators. Nevertheless, it still exposes an &lt;strong&gt;&lt;code&gt;unsubscribe()&lt;/code&gt;&lt;/strong&gt; function to terminate it programmatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;myComponentRef&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;myOutput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Unsubscribes to listen only the first event, if any&lt;/span&gt;
   &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is also automatically completed when the component, or directive, is destroyed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fflrl603ey9vwg9nael4l.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fflrl603ey9vwg9nael4l.jpeg" alt="With new OutputEmitterRef you cannot use the ** raw `pipe()` endraw ** function, but it is automatically completed when the component is destroyed" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  New rxjs-interop functions
&lt;/h2&gt;

&lt;p&gt;To further enhance the capabilities of this new API, two additional functions have been introduced in the &lt;strong&gt;RxJs Interop&lt;/strong&gt; package.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;outputFromObservable()&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Thanks to the brand new &lt;strong&gt;&lt;code&gt;outputFromObservable()&lt;/code&gt;&lt;/strong&gt; function, you can now create an output starting from an &lt;strong&gt;Observable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The generated output emits each new value emitted by the &lt;strong&gt;Observable&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OutputRef&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;outputFromObservable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core/rxjs-interop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-timer-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`...`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyTimerComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

 &lt;span class="nl"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OutputRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;outputFromObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

 &lt;span class="nx"&gt;timerAlias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;outputFromObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timerChange&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both the &lt;strong&gt;Observable&lt;/strong&gt; and the output are automatically completed when the component, or directive, is destroyed.&lt;/p&gt;

&lt;p&gt;If an error occurs, the &lt;strong&gt;Observable&lt;/strong&gt; is interrupted, consequently the output stops emitting and the error propagates (if not caught).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;outputToObservable()&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Thanks to the new &lt;strong&gt;&lt;code&gt;outputToObservable()&lt;/code&gt;&lt;/strong&gt; function we can instead transform an output into an &lt;strong&gt;Observable&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;outputToObservable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core/rxjs-interop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-parent-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;my-component /&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyParentComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;myComponentRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="nf"&gt;outputToObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;myComponentRef&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;myOutput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Manual subscription:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, both the &lt;strong&gt;Observable&lt;/strong&gt; and the output are automatically completed when the component, or directive, is destroyed.&lt;/p&gt;

&lt;p&gt;Furthermore, due to the absence of errors in the outputs, the resulting &lt;strong&gt;Observable&lt;/strong&gt; never emits error notifications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thanks for reading so far 🙏
&lt;/h2&gt;

&lt;p&gt;I’d like to have your feedback so please leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt; or &lt;strong&gt;follow&lt;/strong&gt;. 👏&lt;/p&gt;

&lt;p&gt;Then, if you really liked it, &lt;strong&gt;share it&lt;/strong&gt; among your community, tech bros and whoever you want. And don’t forget to &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;. 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular HostAttributeToken: the new way to inject attributes</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Sun, 21 Apr 2024 22:00:00 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/angular-hostattributetoken-the-new-way-to-inject-attributes-45ia</link>
      <guid>https://dev.to/davidepassafaro/angular-hostattributetoken-the-new-way-to-inject-attributes-45ia</guid>
      <description>&lt;p&gt;Over the latest months &lt;strong&gt;Angular&lt;/strong&gt; has been evolving rapidly, introducing new features and a ton of improvements, many of these with the aim of improving maintainability and performance.&lt;/p&gt;

&lt;p&gt;In this article I want to introduce you to the latest addition brought by &lt;strong&gt;Angular v17.3.0&lt;/strong&gt;: the new &lt;strong&gt;HostAttributeToken&lt;/strong&gt; class.&lt;/p&gt;

&lt;p&gt;This new API allows you to inject host attributes using the &lt;strong&gt;&lt;code&gt;inject()&lt;/code&gt; function&lt;/strong&gt;, similar to the functionality of the &lt;strong&gt;@Attribute&lt;/strong&gt; decorator.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;@Attribute&lt;/strong&gt; decorator is perhaps the lesser-known Angular decorators.&lt;br&gt;
Therefore, before delving into how the &lt;strong&gt;HostAttributeToken class&lt;/strong&gt; works, let’s take a moment to review the fundamentals.&lt;/p&gt;


&lt;h2&gt;
  
  
  @Attribute: do you really need an input?
&lt;/h2&gt;

&lt;p&gt;Let’s start from a simple scenario in which you want to develop a component requiring a &lt;strong&gt;configurable property&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Specifically, you want to provide this property as a &lt;strong&gt;constant string literal&lt;/strong&gt;, because it will not change throughout runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;my-divider&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;"small"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you would normally do is to create an &lt;strong&gt;input&lt;/strong&gt; for that property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;DividerSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;small&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;big&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-divider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;hr [class]="size" /&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDivider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DividerSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is fine and works quite well. Perhaps too much…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7if8wf9uvxma088sl8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7if8wf9uvxma088sl8s.png" alt="Meme - Well done. BUT..." width="639" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By creating an input, you are instructing &lt;strong&gt;Angular&lt;/strong&gt; to create a binding to that property and check it during each change detection cycle.&lt;/p&gt;

&lt;p&gt;That is really excessive, you only need that property to be &lt;strong&gt;checked once&lt;/strong&gt; during component initialization. 🤯&lt;/p&gt;

&lt;p&gt;To make this more performant you can instead inject the &lt;strong&gt;host-element attribute&lt;/strong&gt; in the &lt;strong&gt;constructor&lt;/strong&gt; thanks to the &lt;strong&gt;@Attribute&lt;/strong&gt; decorator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;DividerSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;small&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;big&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-divider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;hr [class]="size" /&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDivider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;size&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;strong&gt;@Attribute&lt;/strong&gt;, Angular will read the value only &lt;strong&gt;once&lt;/strong&gt; and never again.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; This approach works as well with &lt;strong&gt;Directives&lt;/strong&gt;, feel free to give it a shot!!!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Now that we have covered the basics, let me introduce you to the main topic of this article: new &lt;strong&gt;HostAttributeToken&lt;/strong&gt; class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc99124za1r8d580zia3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc99124za1r8d580zia3g.png" alt="Meme - Finally, let's talk about new stuff!" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inject an Attribute using HostAttributeToken class
&lt;/h2&gt;

&lt;p&gt;Since the release of Angular 14 there is now a cleaner approach to inject providers without using the constructor class: the &lt;strong&gt;&lt;code&gt;inject()&lt;/code&gt;&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;Up until now, this &lt;strong&gt;&lt;code&gt;inject()&lt;/code&gt; function&lt;/strong&gt; allowed to &lt;strong&gt;inject&lt;/strong&gt; easily components, directives and pipes, but it was missing a method to inject host attributes.&lt;/p&gt;

&lt;p&gt;And that’s precisely why the &lt;strong&gt;HostAttributeToken class&lt;/strong&gt; was introduced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HostAttributeToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;DividerSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;small&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;big&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-divider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;hr [class]="size" /&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDivider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HostAttributeToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;size&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By injecting an &lt;strong&gt;HostAttributeToken class&lt;/strong&gt; within the &lt;strong&gt;inject function&lt;/strong&gt;, you get the corresponding &lt;strong&gt;host-element attribute&lt;/strong&gt; value.&lt;/p&gt;

&lt;p&gt;This new API works similarly to &lt;strong&gt;@Attribute&lt;/strong&gt;, with a notable difference: instead of returning &lt;strong&gt;&lt;code&gt;null&lt;/code&gt;&lt;/strong&gt; when the attribute is missing, it throws an &lt;strong&gt;error&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnl2p38wmoj5ik8doik0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnl2p38wmoj5ik8doik0.png" alt="🔥 Error: NG0201: No provider for HostAttributeToken size found. 🔥" width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This change was made to align the behavior with other injection tokens.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thanks for reading so far 🙏
&lt;/h2&gt;

&lt;p&gt;I’d like to have your feedback so please leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt; or &lt;strong&gt;follow&lt;/strong&gt;. 👏&lt;/p&gt;

&lt;p&gt;Then, if you really liked it, &lt;strong&gt;share it&lt;/strong&gt; among your community, tech bros and whoever you want. And don’t forget to &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;. 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular Signal Queries: Simplifying DOM Querying</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Mon, 15 Apr 2024 07:00:00 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/angular-signal-queries-simplifying-dom-querying-hmh</link>
      <guid>https://dev.to/davidepassafaro/angular-signal-queries-simplifying-dom-querying-hmh</guid>
      <description>&lt;p&gt;Following &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-signal-inputs-road-to-signal-components-32cl"&gt;Signal Inputs&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-model-inputs-two-way-binding-inputs-with-signals-2nc7"&gt;Model Inputs&lt;/a&gt;&lt;/strong&gt;, another Signal API has landed in the Angular ecosystem with the release of v17.2.0: &lt;strong&gt;Signal Queries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signal Queries&lt;/strong&gt; offer an alternative approach to the decorator-based queries, namely &lt;strong&gt;@ViewChild&lt;/strong&gt;, &lt;strong&gt;@ViewChildren&lt;/strong&gt;, &lt;strong&gt;@ContentChild&lt;/strong&gt; and &lt;strong&gt;@ContentChildren&lt;/strong&gt;, supplying query results as a &lt;strong&gt;Signal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With queries, you can retrieve references to components, directives, DOM elements, and more. Let’s see what has changed with &lt;strong&gt;Signal Queries&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  View queries
&lt;/h2&gt;

&lt;p&gt;View queries allow you to retrieve and interact directly with elements in a component’s own template, also known as &lt;strong&gt;view&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Both &lt;strong&gt;@ViewChild&lt;/strong&gt; and &lt;strong&gt;@ViewChildren&lt;/strong&gt; now have a &lt;strong&gt;Signal&lt;/strong&gt; counterpart.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bjxthvyx491eilit2hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bjxthvyx491eilit2hw.png" alt="@ViewChild to viewChild(), @ViewChildren to viewChildren()" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  viewChild
&lt;/h3&gt;

&lt;p&gt;Using the new &lt;strong&gt;&lt;code&gt;viewChild()&lt;/code&gt;&lt;/strong&gt; function you can retrieve a single element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;input #inputEl /&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;inputElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ElementRef&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;viewChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inputEl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function accepts every parameter that &lt;strong&gt;@ViewChild&lt;/strong&gt; supports and offers the same functionalities, providing you the query result as a &lt;strong&gt;Signal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When a query does not find any result its value is &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;, this happens commonly using &lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-control-flow-the-complete-guide-1pan"&gt;Control Flow&lt;/a&gt;&lt;/strong&gt; statement like &lt;strong&gt;&lt;code&gt;@if&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;@for&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
Because of this, a &lt;strong&gt;&lt;code&gt;viewChild()&lt;/code&gt;&lt;/strong&gt; &lt;strong&gt;Signal&lt;/strong&gt; value type is &lt;strong&gt;&lt;code&gt;ElementRef | undefined&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you are sure about the presence of at least one matching result, you can use the dedicated &lt;strong&gt;&lt;code&gt;viewChild.required()&lt;/code&gt;&lt;/strong&gt; function and get rid of &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;input #inputEl /&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;inputElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inputEl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But be careful, when a &lt;strong&gt;required&lt;/strong&gt; query fails to find any results, &lt;strong&gt;Angular&lt;/strong&gt; throws a dedicated &lt;strong&gt;error&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqmvztiirfgc66k79g1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqmvztiirfgc66k79g1y.png" alt="Angular Error NG0951" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  viewChildren
&lt;/h3&gt;

&lt;p&gt;Using the new &lt;strong&gt;&lt;code&gt;viewChildren()&lt;/code&gt;&lt;/strong&gt; function you can retrieve multiple elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewChildren&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;input #inputEl /&amp;gt;

    @if (showSecondInput) {
      &amp;lt;input #inputEl /&amp;gt;
    }
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;showSecondInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;inputElementList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;viewChildren&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inputEl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly to &lt;strong&gt;&lt;code&gt;viewChild()&lt;/code&gt;&lt;/strong&gt; API, the &lt;strong&gt;&lt;code&gt;viewChildren()&lt;/code&gt;&lt;/strong&gt; function accepts every parameter that &lt;strong&gt;@ViewChildren&lt;/strong&gt; supports and offers the same functionalities, providing you the query result as a &lt;strong&gt;Signal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When a &lt;strong&gt;&lt;code&gt;viewChildren()&lt;/code&gt;&lt;/strong&gt; query does not find any result, its value is an &lt;strong&gt;empty array&lt;/strong&gt;, this guarantees the results array is always initialized.&lt;/p&gt;




&lt;h2&gt;
  
  
  Content queries
&lt;/h2&gt;

&lt;p&gt;Content queries allow you to retrieve and interact directly with elements in a component’s content.&lt;/p&gt;

&lt;p&gt;A component’s content is represented by the elements provided thought &lt;strong&gt;content projection&lt;/strong&gt;, nesting elements inside the component tag in the template where it is used. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;my-component&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt; Hello ;) &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;#inputEl&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/my-component&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; apart for the target template where the queries are performed, &lt;strong&gt;content queries&lt;/strong&gt; APIs and &lt;strong&gt;view queries&lt;/strong&gt; APIs work identically.&lt;br&gt;
Because of that the next section of the article totally relies on the previous one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Similar to our previous discussion on view queries, both &lt;strong&gt;@ContentChild&lt;/strong&gt; and &lt;strong&gt;@ContentChildren&lt;/strong&gt; now have as well a &lt;strong&gt;Signal&lt;/strong&gt; counterpart.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8x6772u18rewak6pcsct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8x6772u18rewak6pcsct.png" alt="@ContentChild to contentChild(), @ContentChildren to contentChildren()" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  contentChild
&lt;/h3&gt;

&lt;p&gt;Using the new &lt;strong&gt;&lt;code&gt;contentChild()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;contentChild.required()&lt;/code&gt;&lt;/strong&gt; functions you can retrieve a single element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentChild&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div&amp;gt;
      &amp;lt;ng-content /&amp;gt;
    &amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;inputElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ElementRef&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;contentChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inputEl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;inputElementReq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contentChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inputEl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Identically to the &lt;strong&gt;&lt;code&gt;viewChild()&lt;/code&gt;&lt;/strong&gt; function, when a &lt;strong&gt;required &lt;code&gt;contentChild()&lt;/code&gt;&lt;/strong&gt; function query fails to find any results, &lt;strong&gt;Angular&lt;/strong&gt; throws a dedicated error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqmvztiirfgc66k79g1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqmvztiirfgc66k79g1y.png" alt="Angular Error NG0951" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  contentChildren
&lt;/h3&gt;

&lt;p&gt;Using the &lt;strong&gt;&lt;code&gt;contentChildren()&lt;/code&gt;&lt;/strong&gt; function you can retrieve multiple elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentChildren&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div&amp;gt;
      &amp;lt;ng-content /&amp;gt;
    &amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;inputElementList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;contentChildren&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inputEl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Identically to the &lt;strong&gt;&lt;code&gt;viewChildren()&lt;/code&gt;&lt;/strong&gt; function, when a &lt;strong&gt;&lt;code&gt;contentChildren()&lt;/code&gt;&lt;/strong&gt; query does not find any result, its value is an &lt;strong&gt;empty array&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Some rules you need to be careful
&lt;/h2&gt;

&lt;p&gt;This new functions, &lt;strong&gt;&lt;code&gt;viewChild()&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;viewChildren()&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;contentChild()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;contentChildren()&lt;/code&gt;&lt;/strong&gt;, only work if used to declare queries by initializing a component or a directive property.&lt;/p&gt;

&lt;p&gt;Calling them outside of component and directive property initialization will produce no error, but the query will not find any result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewChild&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div #el&amp;gt;&amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;viewChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;el&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// It works!&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;viewChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;el&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// No error&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;myEl&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Signal Queries vs Decorator Queries
&lt;/h2&gt;

&lt;p&gt;Having the queries results as &lt;strong&gt;Signals&lt;/strong&gt; means that we can compose them with other &lt;strong&gt;Signals&lt;/strong&gt;, using &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt; functions.&lt;/p&gt;

&lt;p&gt;This is a significant advantage, as it enhances the flexibility and functionality of our codebase, leading the way to all the improvements in change detection that &lt;strong&gt;Signals&lt;/strong&gt; brought to the framework.&lt;/p&gt;

&lt;p&gt;In addition to that, &lt;strong&gt;Signal Queries&lt;/strong&gt; offer other benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;More predictable timing:&lt;/strong&gt; query results are accessible as soon as they’re available;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simpler API surface:&lt;/strong&gt; every query result is provided as a &lt;strong&gt;Signal&lt;/strong&gt;, and queries with multiple results (&lt;strong&gt;&lt;code&gt;viewChildren()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;contentChildren()&lt;/code&gt;&lt;/strong&gt;) return always a defined array;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved type safety:&lt;/strong&gt; cases with &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt; as possible result are fewer, thanks to &lt;strong&gt;&lt;code&gt;required()&lt;/code&gt;&lt;/strong&gt; functions and default array for multiple results;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;More accurate type inference:&lt;/strong&gt; TypeScript can infer more accurate types when a type predicate is used or when you explicit a &lt;strong&gt;&lt;code&gt;read&lt;/code&gt;&lt;/strong&gt; option;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lazier updates:&lt;/strong&gt; as for all &lt;strong&gt;Signals&lt;/strong&gt;, Angular updates queries results lazily. This means that the read operation are performed only when your code explicitly reads the query results.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Thanks for reading so far 🙏
&lt;/h2&gt;

&lt;p&gt;I’d like to have your feedback so please leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt; or &lt;strong&gt;follow&lt;/strong&gt;. 👏&lt;/p&gt;

&lt;p&gt;Then, if you really liked it, &lt;strong&gt;share it&lt;/strong&gt; among your community, tech bros and whoever you want. And don’t forget to &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;. 👋😁&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular Model Inputs: two-way binding inputs with Signals</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Tue, 09 Apr 2024 07:00:00 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/angular-model-inputs-two-way-binding-inputs-with-signals-2nc7</link>
      <guid>https://dev.to/davidepassafaro/angular-model-inputs-two-way-binding-inputs-with-signals-2nc7</guid>
      <description>&lt;p&gt;Angular journey towards the full integration of Signals has moved forward with the latest release of &lt;strong&gt;Angular v17.2.0&lt;/strong&gt;, introducing a new API to allow two-way binding with Signal Inputs: &lt;strong&gt;Model Inputs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before proceeding, I kindly suggest you to read my previous article “&lt;strong&gt;&lt;a href="https://dev.to/davidepassafaro/angular-signal-inputs-road-to-signal-components-32cl"&gt;Angular Signal Inputs: road to Signal Components&lt;/a&gt;&lt;/strong&gt;”, in which you will found a more exhaust explanation about the advantages of &lt;strong&gt;Signal Inputs&lt;/strong&gt;:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/davidepassafaro" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F775852%2Fafd61a9c-ee2d-41c0-a227-551b790190e8.png" alt="davidepassafaro"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/davidepassafaro/angular-signal-inputs-road-to-signal-components-32cl" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Angular Signal Inputs: road to Signal Components&lt;/h2&gt;
      &lt;h3&gt;Davide Passafaro ・ Apr 6 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#angular&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#frontend&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;This article is strictly connected to the previous, and is meant to fulfill the open point about the &lt;strong&gt;two-way binding&lt;/strong&gt; with &lt;strong&gt;Signal Inputs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now that &lt;strong&gt;Model Inputs&lt;/strong&gt; are available it’s time to deepen them.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to create a Model Input
&lt;/h2&gt;

&lt;p&gt;Just like Signal Inputs, &lt;strong&gt;Model Inputs&lt;/strong&gt; are meant to replace inputs created with the &lt;strong&gt;@Input&lt;/strong&gt; decorator, exposing the input value as a Signal.&lt;/p&gt;

&lt;p&gt;To create a &lt;strong&gt;Model Input&lt;/strong&gt; you just need to use the &lt;strong&gt;&lt;code&gt;model()&lt;/code&gt;&lt;/strong&gt; function provided by &lt;strong&gt;@angular/core&lt;/strong&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModelSignal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;myProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModelSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your input will be typed as &lt;strong&gt;ModelSignal&lt;/strong&gt;, a special type of Signal that Angular internally updates whenever a new value is bound.&lt;/p&gt;

&lt;h3&gt;
  
  
  The update( ) function
&lt;/h3&gt;

&lt;p&gt;Two-way binding allows both parent and child components to update the value of a bonded input and to share then the same identical value.&lt;/p&gt;

&lt;p&gt;To enable the update from the child component, &lt;strong&gt;ModelSignal&lt;/strong&gt; API exposes a dedicated &lt;strong&gt;&lt;code&gt;update()&lt;/code&gt;&lt;/strong&gt; function to update an input based on the current value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;updateProp&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myProp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; - Updated!!!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The two-way binding
&lt;/h3&gt;

&lt;p&gt;Using Angular’s &lt;strong&gt;two-way binding&lt;/strong&gt; syntax when binding a value from the parent component to the child component, the &lt;strong&gt;ModelSignal&lt;/strong&gt; update from the child component will therefore go back up to the parent component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;my-component&lt;/span&gt;
  &lt;span class="na"&gt;[(myProp)]=&lt;/span&gt;&lt;span class="s"&gt;"parentProp"&lt;/span&gt;
  &lt;span class="na"&gt;(myPropChange)=&lt;/span&gt;&lt;span class="s"&gt;"onPropChangeMethod($event)"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/my-component&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both parent and child component will have the property value synced.&lt;br&gt;
The parent component will also get an output notification named as the input name with “&lt;strong&gt;Change&lt;/strong&gt;” appended, carrying the new value as event object.&lt;/p&gt;


&lt;h2&gt;
  
  
  Model Inputs with default and required values
&lt;/h2&gt;

&lt;p&gt;As you probably noticed in the previous examples, by creating a &lt;strong&gt;Model Input&lt;/strong&gt; you can provide to the &lt;strong&gt;&lt;code&gt;model()&lt;/code&gt;&lt;/strong&gt; function a type argument to define the type of the &lt;strong&gt;ModelSignal&lt;/strong&gt; value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModelSignal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;myProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModelSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Due to the &lt;strong&gt;optional&lt;/strong&gt; nature of the input value, &lt;strong&gt;ModelSignal&lt;/strong&gt; values are typed as possibly &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To get rid of those, you can provide a &lt;strong&gt;default value&lt;/strong&gt; to the &lt;strong&gt;&lt;code&gt;model()&lt;/code&gt;&lt;/strong&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;myProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModelSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can define your &lt;strong&gt;Model Inputs&lt;/strong&gt; as required thought a dedicated &lt;strong&gt;&lt;code&gt;model.required()&lt;/code&gt;&lt;/strong&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;myRequiredProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModelSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Input options: alias and transform function
&lt;/h2&gt;

&lt;p&gt;As classic Angular inputs, &lt;strong&gt;Model Inputs&lt;/strong&gt; support also the &lt;strong&gt;&lt;code&gt;alias&lt;/code&gt;&lt;/strong&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;myProp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default-value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myPropAlias&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Allowing us to decouple the child component input variable name and the DOM property name used by parent components to bound the input value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;my-component&lt;/span&gt; &lt;span class="na"&gt;[(myPropAlias)]=&lt;/span&gt;&lt;span class="s"&gt;"parentProp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/my-component&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Where is the transform( ) function?
&lt;/h3&gt;

&lt;p&gt;Regarding the &lt;strong&gt;&lt;code&gt;transform()&lt;/code&gt;&lt;/strong&gt; function, the last classic inputs option we are familiar with, the &lt;strong&gt;&lt;code&gt;model()&lt;/code&gt;&lt;/strong&gt; function does not support it.&lt;/p&gt;

&lt;p&gt;This make sense to me, just think about the conflicts between the two-way nature of &lt;strong&gt;Model Inputs&lt;/strong&gt;, and the role of the &lt;strong&gt;&lt;code&gt;transform()&lt;/code&gt;&lt;/strong&gt; function to transform the input value only inside a component.&lt;/p&gt;

&lt;p&gt;Luckily, you can overcome this absence using the &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt; function, which allows you to define derived values starting from a Signal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModelSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;myProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModelSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;myComposedProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;modelOptional&lt;/span&gt;&lt;span class="p"&gt;()?.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way the value defined using the &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt; function is confined inside child component.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thanks for reading so far 🙏
&lt;/h2&gt;

&lt;p&gt;I’d like to have your feedback so please leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt; or &lt;strong&gt;follow&lt;/strong&gt;. 👏&lt;/p&gt;

&lt;p&gt;And if you really liked it please &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;. 👋&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular Signal Inputs: road to Signal Components</title>
      <dc:creator>Davide Passafaro</dc:creator>
      <pubDate>Sat, 06 Apr 2024 18:52:17 +0000</pubDate>
      <link>https://dev.to/davidepassafaro/angular-signal-inputs-road-to-signal-components-32cl</link>
      <guid>https://dev.to/davidepassafaro/angular-signal-inputs-road-to-signal-components-32cl</guid>
      <description>&lt;p&gt;Angular v17.1.0 has been released recently and it introduced a new amazing &lt;strong&gt;input&lt;/strong&gt; API designed to enable early access to &lt;strong&gt;Signal Inputs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signal Inputs&lt;/strong&gt; introduction is the initial act of the upcoming rise of &lt;strong&gt;Signal Components&lt;/strong&gt; and &lt;strong&gt;zoneless&lt;/strong&gt; Angular application, enhancing already both code quality and developer experience. Let’s delve into how they work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0umog5zwxp7pxdly0ayj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0umog5zwxp7pxdly0ayj.png" alt="TL;DR: new signal inputs finally arrived in the Angular ecosystem&amp;lt;br&amp;gt;
" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Bye @Input decorator; Welcome input( ) function
&lt;/h2&gt;

&lt;p&gt;Creating a &lt;strong&gt;Signal Input&lt;/strong&gt; is quite simple:&lt;br&gt;
rather than creating an input using the &lt;strong&gt;@Input&lt;/strong&gt; decorator, you should now use the &lt;strong&gt;&lt;code&gt;input()&lt;/code&gt;&lt;/strong&gt; function provided by &lt;strong&gt;@angular/core&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s see an example creating an input of string type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;myProp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Using the &lt;strong&gt;&lt;code&gt;input()&lt;/code&gt;&lt;/strong&gt; function your inputs will be typed as &lt;strong&gt;InputSignal&lt;/strong&gt;, a special type of read-only Signal defined as following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An &lt;strong&gt;InputSignal&lt;/strong&gt; is similar to a non-writable signal except that it also carries additional type-information for transforms, and that Angular internally updates the signal whenever a new value is bound.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More specifically your &lt;strong&gt;Signal Inputs&lt;/strong&gt; will be typed as the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;myProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReadT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WriteT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReadT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReadT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Where &lt;strong&gt;ReadT&lt;/strong&gt; represents the type of the signal value and &lt;strong&gt;WriteT&lt;/strong&gt; represents the type of the expected value from the parent.&lt;br&gt;
Although these types are often the same, I’ll delve deeper into their role and differences discussing the &lt;strong&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/strong&gt; function later on.&lt;/p&gt;

&lt;p&gt;Let’s go back to the previous example focusing on the input value type:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;myProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Those &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt; are given by the &lt;strong&gt;optional&lt;/strong&gt; nature of the input value.&lt;/p&gt;

&lt;p&gt;To define your input as &lt;strong&gt;required&lt;/strong&gt;, and thus get rid of those nasty &lt;strong&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt;, the input API offers a dedicated &lt;strong&gt;&lt;code&gt;required()&lt;/code&gt;&lt;/strong&gt; function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;myProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Alternatively you can provide a &lt;strong&gt;default value&lt;/strong&gt; to the &lt;strong&gt;&lt;code&gt;input()&lt;/code&gt;&lt;/strong&gt; function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;myProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  No more ngOnChanges()
&lt;/h2&gt;

&lt;p&gt;Nowadays you typically use &lt;strong&gt;ngOnChanges&lt;/strong&gt; and &lt;strong&gt;setter&lt;/strong&gt; functions to perform actions when an input is updated.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Signal Inputs&lt;/strong&gt; you can take advantage of the great flexibility of Signals to get rid of those functions using two powerful tools: &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Computed Signals
&lt;/h3&gt;

&lt;p&gt;Using &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt; you can easily define derived values starting from your inputs, one or more, that will be always updated based on the latest values:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;descriptionLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So each time &lt;strong&gt;&lt;code&gt;description&lt;/code&gt;&lt;/strong&gt; value is modified, the value of &lt;strong&gt;&lt;code&gt;descriptionLength&lt;/code&gt;&lt;/strong&gt; is recalculated and updated accordingly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Effect
&lt;/h3&gt;

&lt;p&gt;With &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt; you can define side effects to run when your inputs, one or more, are updated.&lt;/p&gt;

&lt;p&gt;For example, imagine you need to update a third-party script you are using to build your chart component when an input is updated:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Chart&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;third-party-charts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;chartData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;onCleanup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chartData&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

      &lt;span class="nf"&gt;onCleanup&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or even perform an http request:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;myId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nl"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;onCleanup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`myurl/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;myId&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nf"&gt;onCleanup&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Using &lt;strong&gt;&lt;code&gt;computed()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;effect()&lt;/code&gt;&lt;/strong&gt; will make your components more robust and optimized, enhancing also a lot the maintainability of the code.&lt;/p&gt;


&lt;h2&gt;
  
  
  Alias and transform function
&lt;/h2&gt;

&lt;p&gt;In order to guarantee a smoother migration from decorator-based inputs, &lt;strong&gt;Signal Inputs&lt;/strong&gt; supports also &lt;strong&gt;&lt;code&gt;alias&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/strong&gt; function properties:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;textLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;descriptionText&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In particular, thanks to &lt;strong&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/strong&gt; function you can define a function that manipulates your input before it is available in the component scope and this is where the difference between &lt;strong&gt;ReadT&lt;/strong&gt; and &lt;strong&gt;WriteT&lt;/strong&gt; comes into play.&lt;/p&gt;

&lt;p&gt;In fact using the &lt;strong&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/strong&gt; function can create a mismatch between the type of the value being set from the parent, represented by &lt;strong&gt;WriteT&lt;/strong&gt;, and the type of the value stored inside your &lt;strong&gt;Signal Input&lt;/strong&gt;, represented by &lt;strong&gt;ReadT&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For this reason, when creating a &lt;strong&gt;Signal Input&lt;/strong&gt; with the &lt;strong&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/strong&gt; function you can specify both &lt;strong&gt;ReadT&lt;/strong&gt; and &lt;strong&gt;WriteT&lt;/strong&gt; as the function type arguments:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mySimpleProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReadT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WriteT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReadT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReadT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;

&lt;span class="nx"&gt;myTransformedProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InputSignal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReadT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WriteT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReadT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WriteT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;transformFunction&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can see, without the &lt;strong&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/strong&gt; function the value of &lt;strong&gt;WriteT&lt;/strong&gt; is set as identical to &lt;strong&gt;ReadT&lt;/strong&gt;, while using the &lt;strong&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/strong&gt; function both &lt;strong&gt;ReadT&lt;/strong&gt; and &lt;strong&gt;WriteT&lt;/strong&gt; are defined distinctly.&lt;/p&gt;


&lt;h2&gt;
  
  
  What about two-way binding?
&lt;/h2&gt;

&lt;p&gt;There is no way to implement &lt;strong&gt;two-way binding&lt;/strong&gt; with &lt;strong&gt;Signal Inputs&lt;/strong&gt;, but there is a dedicated API called &lt;strong&gt;Model Input&lt;/strong&gt; that exposes an &lt;strong&gt;&lt;code&gt;update()&lt;/code&gt;&lt;/strong&gt; function to fulfill this behavior.&lt;/p&gt;

&lt;p&gt;👇🏼 You can find my dedicated article here: 👇🏼&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/davidepassafaro" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F775852%2Fafd61a9c-ee2d-41c0-a227-551b790190e8.png" alt="davidepassafaro"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/davidepassafaro/angular-model-inputs-two-way-binding-inputs-with-signals-2nc7" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Angular Model Inputs: two-way binding inputs with Signals&lt;/h2&gt;
      &lt;h3&gt;Davide Passafaro ・ Apr 9 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#angular&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#frontend&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;






&lt;h2&gt;
  
  
  Thanks for reading so far 🙏
&lt;/h2&gt;

&lt;p&gt;I’d like to have your feedback so please leave a &lt;strong&gt;comment&lt;/strong&gt;, &lt;strong&gt;like&lt;/strong&gt; or &lt;strong&gt;follow&lt;/strong&gt;. 👏&lt;/p&gt;

&lt;p&gt;And if you really liked it please &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/davide-passafaro/" rel="noopener noreferrer"&gt;follow me on LinkedIn&lt;/a&gt;&lt;/strong&gt;. 👋&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
