<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Enea Jahollari on Medium]]></title>
        <description><![CDATA[Stories by Enea Jahollari on Medium]]></description>
        <link>https://medium.com/@eneajahollari?source=rss-eb2c15cb2c38------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*LFs2zwHSvvAuJzTH2I3FIQ.jpeg</url>
            <title>Stories by Enea Jahollari on Medium</title>
            <link>https://medium.com/@eneajahollari?source=rss-eb2c15cb2c38------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 19 Jun 2026 13:56:57 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@eneajahollari/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Everything you need to know about the resource API in Angular ⚡️]]></title>
            <link>https://eneajahollari.medium.com/everything-you-need-to-know-about-the-resource-api-in-angular-%EF%B8%8F-7f56a5c5aafc?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/7f56a5c5aafc</guid>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[state-management]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Wed, 23 Oct 2024 13:34:05 GMT</pubDate>
            <atom:updated>2024-10-23T13:34:05.479Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DHDtpVmF-u-gIOA--gMpcw.png" /></figure><p>In v19, Angular will introduce a new API for loading resources. This would allow us to fetch data from an API, know about the status of the request, and update the data locally when needed.</p><h3>Intro</h3><p>The resource API is straightforward in its core. Let’s see the most simple example of how to use it.</p><pre>import { resource } from &quot;@angular/core&quot;;<br><br>@Component({})<br>export class MyComponent {<br>  todoResource = resource({<br>    loader: () =&gt; {<br>      return Promise.resolve({ id: 1, title: &quot;Hello World&quot;, completed: false });<br>    },<br>  });<br><br>  constructor() {<br>    effect(() =&gt; {<br>        console.log(&quot;Value: &quot;, this.todoResource.value());<br>        console.log(&quot;Status: &quot;, this.todoResource.status());<br>        console.log(&quot;Error: &quot;, this.todoResource.error());<br>    })<br>  }<br>}</pre><p>First, we can notice that the resource API uses Promises by default for the loader parameter. The other one is that the resource API will return an WritableResource object, which helps us to update the data locally when needed.</p><p>We can read the current value of the resource by using the value signal, the status of the resource by using the status signal, and the error of the resource by using the error signal.</p><p>The code above will print the following:</p><pre>Value: undefined<br>Status: &#39;loading&#39;<br>Error: undefined<br><br>Value: { id: 1, title: &quot;Hello World&quot;, completed: false }<br>Status: &#39;resolved&#39;<br>Error: undefined</pre><h3>Updating the data locally</h3><p>Let’s see how we can update the data locally.</p><pre>import { resource } from &quot;@angular/core&quot;;<br><br>@Component({<br>    template: `<br>        &lt;button (click)=&quot;updateTodo()&quot;&gt;Update&lt;/button&gt;<br>    `<br>})<br>export class MyComponent {<br>  todoResource = resource({<br>    loader: () =&gt; {<br>      return Promise.resolve({ id: 1, title: &quot;Hello World&quot;, completed: false });<br>    },<br>  });<br><br>  updateTodo() {<br>    this.todoResource.value.update((value) =&gt; {<br>      if (!value) return undefined;<br>      <br>      return { ...value, title: &quot;updated&quot; };<br>    });<br>  }<br>}</pre><p>We can update the data locally by using the update method of the value signal.</p><p>This will print the following:</p><pre>Value: { id: 1, title: &quot;updated&quot;, completed: false }<br>Status: &#39;local&#39;<br>Error: undefined</pre><p>The ‘local’ status means that the data was updated locally.</p><h3>Loading the data</h3><p>Let’s make a proper request to the server. Let’s load some todos from the <a href="https://jsonplaceholder.typicode.com/">JSONPlaceholder API</a>.</p><pre>interface Todo {<br>  id: number;<br>  title: string;<br>  completed: boolean;<br>}<br><br>@Component()<br>export class MyComponent {<br>  todosResource = resource({<br>    loader: () =&gt; {<br>      return fetch(`https://jsonplaceholder.typicode.com/todos?_limit=10`)<br>        .then((res) =&gt; res.json() as Promise&lt;Todo[]&gt;);<br>    },<br>  });<br>}</pre><p>This todosResource will start to make the request to the server immediately after it has been created.</p><p>Of course, the todosResource will not have a value yet, because the request is still in progress.</p><p>The code above will print the following:</p><pre>Value: undefined<br>Status: &#39;loading&#39;<br>Error: undefined<br><br>Value: [{ id: 1, title: &quot;Hello World&quot;, completed: false }, { id: 2, title: &quot;Hello World&quot;, completed: false }, ...]<br>Status: &#39;resolved&#39;<br>Error: undefined</pre><h3>Refreshing the data</h3><p>Let’s say we want to refresh the data when the user clicks on a button.</p><pre>import { resource } from &quot;@angular/core&quot;;<br><br>@Component()<br>export class MyComponent {<br>  todosResource = resource({<br>    loader: () =&gt; {<br>      return fetch(`https://jsonplaceholder.typicode.com/todos?_limit=10`)<br>        .then((res) =&gt; res.json() as Promise&lt;Todo[]&gt;);<br>    },<br>  });<br><br>  refresh() {<br>    this.todosResource.refresh();<br>  }<br>}</pre><p>The refresh function will run the loader function again. If you call the refresh function multiple times, the loader function will be called only once until the previous request is finished (like exhaustMap behavior in RxJS).</p><h3>Loading specific data based on other signals</h3><p>Let’s say we want to load the todos based on a todoId signal.</p><pre>import { resource } from &quot;@angular/core&quot;;<br><br>@Component()<br>export class MyComponent {<br>  todoId = signal(1);<br><br>  todoResource = resource({<br>    loader: () =&gt; {<br>      return fetch(<br>        `https://jsonplaceholder.typicode.com/todos/${this.todoId()}`<br>      ).then((res) =&gt; res.json() as Promise&lt;Todo&gt;);<br>    },<br>  });<br>}</pre><p>This will work fine, but one thing to notice is that loader is untracked and that means, that if the todoId signal changes, the load won&#39;t be called again. Let&#39;s make it more reactive!</p><h3>Separate the request and the loader</h3><p>We want our resource to refresh the data (call the loader again) every time the todoId changes. For this, we can use the request field of the resource. We can pass a signal to it, and it will be tracked.</p><pre>todoResource = resource({<br>    request: this.todoId, <br>    loader: ({ request: todoId }) =&gt; {  <br>        return fetch( <br>          `https://jsonplaceholder.typicode.com/todos/${todoId}`,<br>        ).then((res) =&gt; res.json() as Promise&lt;Todo&gt;);<br>    },<br>});</pre><p>Now, when the todoId signal changes, the resource API will automatically fetch the new data.</p><p>What if we have previous unfinished requests? Let’s say we want to cancel the previous request when the todoId changes. Well, we can do that by using the abortSignal that is passed to the loader function.</p><pre>todoResource = resource({<br>    request: this.todoId, <br>    loader: ({ request: todoId, abortSignal }) =&gt; {  <br>        return fetch( <br>          `https://jsonplaceholder.typicode.com/todos/${todoId}`, <br>          { signal: abortSignal } <br>        ).then((res) =&gt; res.json() as Promise&lt;Todo&gt;);<br>    },<br>});</pre><p>This will cancel the previous request when the todoId changes and if the previous request is still in progress.</p><p>We can also have multiple request dependencies, for example:</p><pre>limit = signal(10);<br>query = signal(&#39;&#39;);<br><br>todosResource = resource({<br>    request: () =&gt; ({ limit: this.limit(), query: this.query() }),<br>    loader: ({ request, abortSignal }) =&gt; {   <br>        const { limit, query } = request as { limit: number; query: string };<br>        return fetch(<br>          `https://jsonplaceholder.typicode.com/todos?_limit=${limit}&amp;query=${query}`, <br>          { signal: abortSignal } <br>        ).then((res) =&gt; res.json() as Promise&lt;Todo[]&gt;);<br>    },<br>});</pre><p>Now, the todosResource will make the request based on the limit and query signals, and the loader function will be able to use those signals to make the request, and anytime the limit or query signal changes, the loader function will be called again.</p><h3>What happens when we have a request in progress and update data locally?</h3><p>If that’s the case, the resource API will automatically update the data locally, but cancel the ongoing request.</p><h3>How to postpone making the API request?</h3><p>There are cases, when we don’t want to make the API request immediately, but do it only on some conditions only. A feature of the loader is that it won’t make the API request if the request returns undefined. We can use that as the example below:</p><pre>query = signal(&#39;&#39;);<br>pageIsActive = signal(true);<br><br>todosResource = resource({<br>    request: () =&gt; pageIsActive() ? this.query(): undefined,<br>    loader: ({ request: query, abortSignal }) =&gt; {   <br>        return fetch(<br>          `https://jsonplaceholder.typicode.com/todos?query=${query}`, <br>          { signal: abortSignal } <br>        ).then((res) =&gt; res.json() as Promise&lt;Todo[]&gt;);<br>    },<br>});</pre><p>This enables us to only make the API request when the pageIsActive() signal is true . This may be the case when you use the resource function in a service.</p><h3>Create more reusable resources</h3><p>By separating reactive values from the loader function, we can move the logic of the loader function to a separate function, and store it where we want.</p><p>Before:</p><pre>todoResource = resource({<br>    request: this.todoId,<br>    loader: ({ request: todoId, abortSignal }) =&gt; {  <br>        return fetch(<br>          `https://jsonplaceholder.typicode.com/todos/${todoId}`, <br>          { signal: abortSignal } <br>        ).then((res) =&gt; res.json() as Promise&lt;Todo&gt;);<br>    },<br>});</pre><p>After:</p><pre>import { ResourceLoaderParams } from &quot;@angular/core&quot;;<br><br>function todoLoader({ request: todoId, abortSignal }: ResourceLoaderParams&lt;number&gt;): Promise&lt;Todo&gt; {<br>    return fetch(<br>      `https://jsonplaceholder.typicode.com/todos/${todoId}`, <br>      { signal: abortSignal } <br>    ).then((res) =&gt; res.json() as Promise&lt;Todo&gt;);<br>}<br><br>todoResource = resource({ request: this.todoId, loader: todoLoader });</pre><p>The todoLoader can be moved anywhere, and also can be reused by other resources. The ResourceLoaderParams type is a type that contains all the information that is needed to make the request, and the request parameter is the one that is passed to the loader function.</p><h3>RxResource -&gt; The observable-based resource API</h3><p>Angular has always been about using Observables when it comes to data loading. This means, that we can use Observables to derive the data loading instead of using signals &amp; promises.</p><p>To make this possible, we can use the rxResource function.</p><pre>import { rxResource } from &quot;@angular/core/rxjs-interop&quot;;<br><br>@Component()<br>export class MyComponent {<br>  limit = signal(10);<br><br>  todosResource = rxResource({<br>    request: this.limit,<br>    loader: (limit) =&gt; {<br>      return this.http.get&lt;Todo[]&gt;(<br>        `https://jsonplaceholder.typicode.com/todos?_limit=${limit}`<br>      );<br>    },<br>  });<br>}</pre><p>This will make the request based on the limit signal, and the loader function will be able to use the limit value to make the request, and same as signals, anytime the limit signal changes, the loader function will be called again and cancel the previous request (same as switchMap behavior in RxJs)</p><p>And same as we can change the local state with the signals, we can also change the local state with the observable implementation in the rxResource function.</p><h3>Summary</h3><p>We have 2 new primitives [<strong>resource</strong>, <strong>rxResource</strong>] that will help us make our life easier when dealing with data loading in Angular. These primitives have been requested for so long now, and will land in v19 as developer previews.</p><p>PR link: <a href="https://github.com/angular/angular/pull/58255">https://github.com/angular/angular/pull/58255</a></p><h4>📹 Detailed explanation from <a href="https://www.youtube.com/@JoshuaMorony">Josh Morony</a></h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FUp6DKUUs45c%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DUp6DKUUs45c&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FUp6DKUUs45c%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/ae910f82c45bd928eaf223583c403da0/href">https://medium.com/media/ae910f82c45bd928eaf223583c403da0/href</a></iframe><h4>📢 Announcements</h4><h3>NgGlühwein 2024</h3><p>For the first time ever the <a href="https://push-based.io/">Push-Based team</a> will host a workshop day on the day before the <strong>NgGlühwein</strong> conference. There will be two workshops held simultaneously:</p><ul><li><a href="https://push-based.io/workshop/nggluehwein-workshop-day-architecting-angular-apps-for-high-performance?mtm_campaign=ejresperfmed"><strong>Architecting Angular Apps for High Performance</strong></a></li><li><a href="https://push-based.io/workshop/nggluehwein-workshop-day-nx-for-scalable-architecture?mtm_campaign=ejresnxmed"><strong>Nx for Scalable Architecture</strong></a></li></ul><p>Join conference for free (in-person &amp; online) 👇: <br><a href="https://www.meetup.com/angular-vienna/events/304004182"><strong>https://www.meetup.com/angular-vienna/events/304004182</strong></a></p><h3>Thanks for reading!</h3><p>If this article was interesting and useful to you, and you want to learn more about Angular, support me by <a href="https://ko-fi.com/eneajahollari">buying me a coffee ☕️</a> or follow me on X (formerly Twitter) <a href="https://twitter.com/Enea_Jahollari">@Enea_Jahollari</a> where I tweet and blog a lot about Angular latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more. 💎</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7f56a5c5aafc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Providing inputs in DI ]]></title>
            <link>https://itnext.io/providing-inputs-in-di-1d75a3ca8e9d?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/1d75a3ca8e9d</guid>
            <category><![CDATA[putin]]></category>
            <category><![CDATA[dependency-injection]]></category>
            <category><![CDATA[angular]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Tue, 28 May 2024 08:07:49 GMT</pubDate>
            <atom:updated>2024-05-30T17:00:21.690Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WSmDcnfUiV7zjVuB.png" /></figure><p>When working with Angular, we often find ourselves in situations where we need to pass data from a parent component to a child component. This is usually done using @Input properties. However, as the application grows, we might find ourselves in a situation where we have to pass the same data through multiple levels of components. This is known as prop drilling and can make our code harder to maintain and understand.</p><p>In this article we will see how we can use the new Signal Inputs and Dependency Injection to provide inputs to components without having to pass them through multiple levels of components.</p><h3>Before Signal Inputs</h3><p>Let’s start by looking at an example of how we would pass data from a parent component to a child component using @Input properties.</p><pre>@Component({<br>  template: `&lt;app-child [data]=&quot;data&quot; /&gt;`,<br>})<br>export class ParentComponent {<br>  @Input() data: string;<br>}<br><br>@Component({<br>  template: `&lt;app-inner-child [data]=&quot;data&quot; /&gt;`,<br>})<br>export class ChildComponent {<br>  @Input() data: string;<br>}<br><br>@Component({<br>  template: `{{ data }}`,<br>})<br>export class InnerChildComponent {<br>  @Input() data: string;<br>}</pre><p>In this example, we have a ParentComponent that passes data to a ChildComponent, which in turn passes the data to an InnerChildComponent. This is a simple example.</p><p>In order to solve this problem, we have used what we call services.</p><p>So, it will look something like this:</p><pre>@Injectable()<br>export class DataService {<br>  data: string;<br><br>  setData(data: string) {<br>    this.data = data;<br>  }<br>}<br><br>@Component({<br>  template: `&lt;app-child /&gt;`,<br>  providers: [DataService],<br>})<br>export class ParentComponent {<br>  dataService = inject(DataService);<br><br>  // using ngOnChanges to update the data in the service<br>  @Input() data: string;<br><br>  ngOnChanges(changes: SimpleChanges) {<br>    if (changes.data) {<br>      this.dataService.setData(this.data);<br>    }<br>  }<br><br>  // or using a setter<br>  @Input() set data(value: string) {<br>    this.dataService.setData(value);<br>  }<br>}<br><br>@Component({<br>  template: `&lt;app-inner-child /&gt;`,<br>})<br>export class ChildComponent {<br>  // no need to inject the service here as we don&#39;t need it here<br>}<br><br>@Component({<br>  template: `{{ dataService.data }}`,<br>})<br>export class InnerChildComponent {<br>  dataService = inject(DataService);<br>}</pre><p>This works great, until we need to convert our components to use OnPush change detection strategy. Because we are not using @Inputs(), Angular cannot check if the data has changed and will not update the view (if the event didn&#39;t come from the child component itself).</p><p>To solve this we have relied on rxjs BehaviorSubject. Why? Because we can subscribe to it and get the latest value whenever it changes and subscribe to changes using async pipe which will trigger markForCheck under the hood that lets Angular know that this component&#39;s data has changed.</p><pre>@Injectable()<br>export class DataService {<br>  private readonly data = new BehaviorSubject&lt;string&gt;(&quot;&quot;);<br>  readonly data$ = this.data.asObservable();<br><br>  setData(data: string) {<br>    this.data.next(data);<br>  }<br>}<br><br>@Component({<br>  template: `{{ dataService.data$ | async }}`,<br>})<br>export class InnerChildComponent {<br>  dataService = inject(DataService);<br>}</pre><p>One other way to solve this would be to inject the parent component itself into the child component and access the data directly.</p><pre>@Component({<br>  template: `{{ parentComponent.data }}`,<br>})<br>export class InnerChildComponent {<br>  parentComponent = inject(ParentComponent);<br>}</pre><p>This is great until you start to hit circular dependency issues.</p><h3>Signal Inputs approach</h3><p>In order to benefit from Angular enhanced change detection, more here:</p><p><a href="https://itnext.io/a-change-detection-zone-js-zoneless-local-change-detection-and-signals-story-9344079c3b9d">A change detection, zone.js, zoneless, local change detection, and signals story 📚</a></p><p>we can use the new Signal Inputs feature.</p><pre>@Component({<br>  template: `&lt;app-child /&gt;`,<br>})<br>export class ParentComponent {<br>  data = input&lt;string&gt;();<br>}<br><br>@Component({<br>  template: `{{ parentComponent.data() }}`,<br>})<br>export class InnerChildComponent {<br>  parentComponent = inject(ParentComponent);<br>}</pre><p>This is the same as the previous example, but we are using signals instead of normal properties. This will still be affected by circular dependency issues.</p><p>What we can do is to have an InjectionToken which can be used to provide this component input in the DI tree.</p><pre>export const DATA = new InjectionToken&lt;Signal&lt;string&gt;&gt;(&quot;DATA&quot;);<br><br>@Component({<br>  template: `&lt;app-child /&gt;`,<br>  providers: [<br>    {<br>      provide: DATA,<br>      useFactory: () =&gt; inject(ParentComponent).data,<br>    },<br>  ],<br>})<br>export class ParentComponent {<br>  data = input&lt;string&gt;();<br>}<br><br>@Component({<br>  template: `{{ data() }}`,<br>})<br>export class InnerChildComponent {<br>  data = inject(DATA);<br>}</pre><p>Let&#39;s break down the code above:</p><p>We have created an InjectionToken called DATA that will hold the signal for the data. Note that it&#39;s a Signal&lt;string&gt; and not just string because we want to be able to read it only where we need it.</p><p>We have provided the DATA token in the ParentComponent&#39;s providers array. We are using the useFactory property because it allows us to inject the ParentComponent and get the data signal from it.</p><p>We are not calling the data signal directly in the useFactory function because we want to be able to read it only where we need it and not have it in the DI tree.</p><p>We have injected the DATA token in the InnerChildComponent and assigned it to the data property. And now we can read the data signal in the template.</p><p>This way we can provide inputs to components without having to pass them through multiple levels of components and without having to rely on services or BehaviorSubjects.</p><p>Also, this is 100% compatible with OnPush change detection strategy, because we are using signals, which are part of the new Angular change detection system and will trigger change detection when the signal changes.</p><p>It is also compatible with Zoneless Angular, because signals are part of the new Angular change detection system and do not rely on Zone.js.</p><p>This is a great way to remove prop drilling from your Angular applications and make your code more maintainable and easier to understand.</p><h3>One more thing</h3><p>We can also read the token in the services provided in the same component or child components.</p><pre>@Injectable()<br>export class DataService {<br>  data = inject(DATA); // data is a signal here<br>  <br>  constructor() {<br>    effect(() =&gt; {<br>      console.log(this.data()); // use data() to make API calls maybe?<br>    });<br>  }<br>}<br><br>@Component({<br>  template: `&lt;app-child /&gt;`,<br>  providers: [<br>    {<br>      provide: DATA,<br>      useFactory: () =&gt; inject(ParentComponent).data,<br>    },<br>    DataService, // &lt;- provide the service here<br>  ],<br>})<br>export class ParentComponent {<br>  data = input&lt;string&gt;();<br>}</pre><h3>Use one token for multiple signal inputs or other signals</h3><p>If you have multiple inputs that you want to provide to a component, you can use a single token and provide an object with multiple signals.</p><pre>export const INPUTS = new InjectionToken&lt;{<br>  data: Signal&lt;string&gt;;<br>  options: Signal&lt;Record&lt;string, string&gt;&gt;;<br>}&gt;(&quot;INPUTS&quot;);<br><br>@Component({<br>  template: `&lt;app-child /&gt;`,<br>  providers: [<br>    {<br>      provide: INPUTS,<br>      useFactory: () =&gt; {<br>        const cmp = inject(ParentComponent);<br>        return {<br>          data: cmp.data, <br>          options: cmp.options,<br>          count: cmp.someNormalSignal,<br>        };<br>      },<br>    },<br>  ],<br>})<br>export class ParentComponent {<br>  data = input&lt;string&gt;();<br>  options = input&lt;Record&lt;string, string&gt;&gt;();<br>  count = signal&lt;number&gt;();<br>}</pre><p>Hope this helps you to remove prop drilling from your Angular applications and make your code more maintainable and easier to understand. 🚀</p><h3>Thanks for reading!</h3><p>If this article was interesting and useful to you, and you want to learn more about Angular, support me by <a href="https://ko-fi.com/eneajahollari">buying me a coffee ☕️</a> or follow me on X (formerly Twitter) <a href="https://twitter.com/Enea_Jahollari">@Enea_Jahollari</a> where I tweet and blog a lot about Angular latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more. 💎</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1d75a3ca8e9d" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/providing-inputs-in-di-1d75a3ca8e9d">Providing inputs in DI 🎁</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Template local variables with @let in Angular]]></title>
            <link>https://itnext.io/template-local-variables-with-let-in-angular-4c6b3adfd9be?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/4c6b3adfd9be</guid>
            <category><![CDATA[variables]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[template]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Fri, 17 May 2024 10:11:04 GMT</pubDate>
            <atom:updated>2024-05-21T07:04:52.365Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0EMxz0fRStWAGn_h.png" /><figcaption>Give me let Angular</figcaption></figure><h3>Give me let Angular</h3><p>If you have worked with Angular long enough, probably at some point you would have wanted to declare a variable inside the template. This is a common use case when you want to store a value that you will use later in the template.</p><p>The most common way to do this is by using a directive like ngIf and assign the value to a variable using the as keyword. For example:</p><pre>&lt;div *ngIf=&quot;user$ | async as user&quot;&gt;<br>  &lt;h1&gt;{{ user.name }}&lt;/h1&gt;<br>&lt;/div&gt;<br><br>&lt;!-- or using the new control flow --&gt;<br>@if (user$ | async; as user) {<br>  &lt;h1&gt;{{ user.name }}&lt;/h1&gt;<br>}</pre><p>What if you’re working with numbers?</p><pre>&lt;div&gt;<br>    @if (points$ | async; as points) {<br>        &lt;h1&gt;You have: {{ points }} points!&lt;/h1&gt;<br>    }<br>&lt;/div&gt;</pre><p>What would you see in the template if points is 0? You would see <strong>NOTHING!</strong> because 0 is a falsy value and when used inside the if block, it will not render the content.</p><p>This is where the new @let block comes into play. The @let block will allow you to declare a variable inside the template and use it later in the template. Let&#39;s see how it works.</p><pre>&lt;div&gt;<br>    @let points = (points$ | async) ?? 0;  <br>    &lt;h1&gt;You have: {{ points }} points!&lt;/h1&gt;<br>&lt;/div&gt;</pre><p>This will render the content even if points is 0. This is because the let block is not checking for falsy values, it&#39;s just declaring a variable at that point in the template.</p><p>Also, one of the most common use cases for the @let block would be to store a variable that allows us to store aliases for complex expressions. For example:</p><pre>@let someField = someService.someSignal().someProperty.someOtherProperty;<br>&lt;div&gt;{{ someField }}&lt;/div&gt;</pre><h3>How to use @let in Angular</h3><p>You can use the new @let in multiple ways:</p><ul><li><strong>With async pipes</strong>:</li></ul><pre>&lt;div&gt;<br>    @let user = (user$ | async) ?? { name: &#39;Guest&#39; };  <br>    &lt;h1&gt;{{ user.name }}&lt;/h1&gt;<br>&lt;/div&gt;</pre><ul><li><strong>With control flow directives</strong>:</li></ul><pre>&lt;div&gt;<br>    @let user = user$ | async;  <br>    @if (user) {<br>        &lt;h1&gt;{{ user.name }}&lt;/h1&gt;<br>    }<br>&lt;/div&gt;</pre><ul><li><strong>Inside @for to refactor code duplications</strong>:</li></ul><pre>&lt;mat-selection-list&gt;<br>    @for (item of items(); track item.id) {<br>        @let isSelected = item.id === selectedId();<br>        &lt;mat-list-option [selected]=&quot;isSelected&quot; [class.selected]=&quot;isSelected&quot;&gt;<br>            {{ item.text }} <br>            @if (isSelected) {<br>                &lt;span&gt;(selected)&lt;/span&gt;<br>            }<br>        &lt;/mat-list-option&gt;<br>    }<br>&lt;/mat-selection-list&gt;</pre><ul><li><strong>With ternary operators</strong>:</li></ul><pre>&lt;div&gt;<br>    @for (game of games; track game.id) {<br>        @let points = calcPoints(game.points &gt; 0 ? game.points : 0);  <br>        &lt;h1&gt;You have: {{ points }} points!&lt;/h1&gt;<br>    }<br>&lt;/div&gt;</pre><ul><li><strong>With basic math operators</strong>:</li></ul><pre>&lt;div&gt;  <br>    @for (game of games; track game.id) {<br>        @let total = previousTotal + game.points;  <br>        &lt;h1&gt;Total points: {{ total }}&lt;/h1&gt;<br>    }<br>&lt;/div&gt;</pre><ul><li><strong>With signals</strong>:</li></ul><pre>&lt;div&gt;  <br>    @let username = user()?.name ?? &#39;Guest&#39;;<br>    &lt;h1&gt;Welcome, {{ username }}&lt;/h1&gt;<br>&lt;/div&gt;</pre><ul><li><strong>Multiple declarations inline or in multiple lines</strong>:</li></ul><pre>&lt;div&gt;  <br>    @let total = count + previousCount, average = calcAverage(count), (can I use `total` here?)<br>    <br>    @let total = count + previousCount, <br>         average = calcAverage(count)<br>    &lt;h1&gt;{{total}}&lt;/h1&gt;<br>&lt;/div&gt;</pre><h3>Good to know</h3><p>Let declaration will work almost the same as let declarations in JavaScript.</p><ul><li>Scoping will work the same as <strong>let</strong> in javascript.</li><li>Type inference just works!</li><li>Let declarations will have precedence to a local let declaration over a component property.</li><li>A let declaration cannot be referenced before it is defined, with the exception when it’s used inside an event handler.</li></ul><p>This feature closes an issue that has been open since Mar 2017</p><p><a href="https://github.com/angular/angular/issues/15280">Template Local Variables · Issue #15280 · angular/angular</a></p><p>In the PR you can see some alternatives that were considered before the @let block was introduced.</p><ul><li>@const instead of @let</li><li>entirely new keyword</li><li>@var instead of @let</li><li>block-like syntax</li></ul><p>More info about the PR is here:</p><p><a href="https://github.com/angular/angular/pull/55848">Start implementation of @let syntax by crisbeto · Pull Request #55848 · angular/angular</a></p><p>That’s it! This is how you can use the new @let block in Angular templates. This feature probably will be available in Angular v18.1, which is expected to be released in the upcoming months.</p><p>Let me know of any other use cases you can think of for the @let block in Angular templates. 🚀</p><h3>Thanks for reading!</h3><p>If this article was interesting and useful to you, and you want to learn more about Angular, support me by <a href="https://ko-fi.com/eneajahollari">buying me a coffee ☕️</a> or follow me on X (formerly Twitter) <a href="https://twitter.com/Enea_Jahollari">@Enea_Jahollari</a> where I tweet and blog a lot about Angular latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more. 💎</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4c6b3adfd9be" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/template-local-variables-with-let-in-angular-4c6b3adfd9be">Template local variables with @let in Angular</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Removing manual change detection calls from my Angular app ⚡️]]></title>
            <link>https://itnext.io/removing-manual-change-detection-calls-from-my-angular-app-%EF%B8%8F-58dfa481deeb?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/58dfa481deeb</guid>
            <category><![CDATA[change-detection]]></category>
            <category><![CDATA[observables]]></category>
            <category><![CDATA[signal]]></category>
            <category><![CDATA[angular]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Tue, 30 Apr 2024 18:52:16 GMT</pubDate>
            <atom:updated>2024-04-30T19:52:03.617Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BEH5WTDtlL1VdNiQ.png" /></figure><p>If you have read my previous articles about Angular change detection, you know what manual change detection calls are and on this article, I will show you how they work and how I’m removing them from my Angular applications.</p><p>Let’s start with a simple example, where I have a service that fetches the user’s name and I want to display it in a component.</p><pre>@Injectable({ providedIn: &#39;root&#39; })<br>export class UserService {<br>  #http = inject(HttpClient);  getUser() {<br>    return this.#http.get&lt;string&gt;(&#39;/api/user&#39;);<br>  }<br>}<br><br>@Component({<br>    template: `&lt;div&gt;{{ username }}&lt;/div&gt;`,<br>})<br>export class UserComponent {<br>  #userService = inject(UserService);<br>  username: string = &#39;&#39;;<br><br>  ngOnInit() {<br>    this.#userService.getUser().pipe(take(1)).subscribe(user =&gt; {<br>      this.username = user.name;<br>    });<br>  }<br>}</pre><p>If you run this code in an Angular application, it will just work! That’s thanks to zone.js. Why is that? Zone.js is intercepting XHR requests that are made and is telling Angular to run change detection that some data has changed. This is why you see the username in the view.</p><blockquote><em>More about it here: </em><a href="https://justangular.com/blog/a-change-detection-zone-js-zoneless-local-change-detection-and-signals-story"><em>A change detection, zone.js, zoneless, local cd, and signals story 📚</em></a></blockquote><p>But what if you want to use ChangeDetectionStrategy.OnPush for better performance in your component?</p><pre>@Component({<br>    template: `&lt;div&gt;{{ username }}&lt;/div&gt;`,<br>    changeDetection: ChangeDetectionStrategy.OnPush,<br>})<br>export class UserComponent { /*...*/ }</pre><p>Now that we have OnPush enabled, our view is not going to be updated when the name changes, because nothing is telling Angular that this component&#39;s data has changed. This is where manual change detection calls come into play.</p><p>To fix this, we can call ChangeDetectorRef&#39;s markForCheck method to tell Angular to mark this component as dirty and to refresh the bindings/interpolations in the next change detection.</p><pre>export class UserComponent {<br>  #cdr = inject(ChangeDetectorRef);<br><br>  ngOnInit() {<br>    this.#userService.getUser().pipe(take(1)).subscribe(user =&gt; {<br>      this.username = user.name;<br>      this.#cdr.markForCheck();<br>    });<br>  }<br>}</pre><p>This is great, and it works fine! Then another feature comes in, and you need to update the user’s name and add a button to change it, and call the markForCheck method again.</p><pre>export class UserComponent {<br>  username?: string;<br>  <br>  handleNameChange(newName: string) {<br>    this.#userService.changeName(newName).pipe(take(1)).subscribe(name =&gt; {<br>      this.username = name;<br>      this.#cdr.markForCheck(); <br>    });<br>  }<br>}</pre><p>As you can see, this can get out of hand quickly, and you can forget to call markForCheck in some places, which can lead to bugs in your application.</p><p>In order to solve this we would use rxjs and observables, and use the async pipe in the template to let Angular know that this component&#39;s data has changed as it calls markForCheck under the hood.</p><blockquote><em>Read more about it here: </em><a href="https://justangular.com/blog/async-pipe-is-not-pure"><em>Async pipe is not pure 🤯</em></a></blockquote><p>Our component would look like this:</p><pre>@Component({<br>    template: `&lt;div&gt;{{ username$ | async }}&lt;/div&gt;`,<br>    changeDetection: ChangeDetectionStrategy.OnPush,<br>    imports: [AsyncPipe]<br>})<br>export class UserComponent {<br>  #userService = inject(UserService);<br>  #cdr = inject(ChangeDetectorRef);<br>  <br>  username$ = new BehaviorSubject&lt;string&gt;(&#39;&#39;); <br><br>  ngOnInit() {<br>    this.#userService.getUser().pipe(take(1)).subscribe(user =&gt; {<br>      this.username$.next(user.name);<br>    });<br>  }<br><br>  handleNameChange(newName: string) {<br>    this.#userService.changeName(newName).pipe(take(1)).subscribe(name =&gt; {<br>      this.username$.next(name);<br>    });<br>  }<br>}</pre><p>This is perfectly valid code, now we won’t need to call markForCheck anymore, and we can be sure that the view will be updated when the data changes.</p><p>Having to create BehaviorSubjects and using the async pipe in the template can be a bit cumbersome, and this is where Angular signals come into play.</p><p>Signals are a new way to handle state in Angular, and they are very powerful and greatly simplify the way we write Angular applications and in the same time improve the performance of our applications, because <strong><em>Angular thinks in signals now</em></strong>.</p><h3>Step by step guide to remove manual change detection</h3><ul><li>[Optional] Use ESLint to find all manual CD calls</li></ul><p>If you’re using ESLint there is a package which you can install that will show you all the manual CD calls in your application.</p><p><a href="https://www.rx-angular.io/">RxAngular</a> publishes an ESLint plugin with a set of ESLint rules for building reactive, performant and Zone-less Angular applications.</p><p>You can find it here: <a href="https://www.rx-angular.io/docs/eslint-plugin">RxAngular ESLint Plugin</a></p><pre>npm install --save-dev @rx-angular/eslint-plugin</pre><p>Enable the rule:</p><pre>{<br>  &quot;parser&quot;: &quot;@typescript-eslint/parser&quot;,<br>  &quot;plugins&quot;: [&quot;@rx-angular&quot;],<br>  &quot;rules&quot;: {<br>    &quot;@rx-angular/no-explicit-change-detection-apis&quot;: &quot;error&quot;,<br>  }<br>}</pre><ul><li>Check why the manual CD call was needed In our case, we are using OnPush and we need to tell Angular when the data has changed.</li></ul><pre>username: string = &#39;&#39;;<br><br>ngOnInit() {<br>    this.#userService.getUser().pipe(take(1)).subscribe(user =&gt; {<br>        this.username = user.name;<br>        this.#cdr.markForCheck();<br>    });<br>}</pre><p>Let’s replace the username field with a signal.</p><pre>- username: string = &#39;&#39;;<br>+ username = signal(&#39;&#39;); // Will be typed as WritableSignal&lt;string&gt;</pre><p>Now we will see that it will throw an error when we try to set a new value to the field inside the subscription.</p><pre>ngOnInit() {<br>    this.#userService.getUser().pipe(take(1)).subscribe(user =&gt; {<br>        // ❌ Type &#39;string&#39; is not assignable to type &#39;WritableSignal&lt;string&gt;&#39;.<br>        this.username = user.name;<br>        this.#cdr.markForCheck();<br>    });<br>}</pre><p>But, if your application is not using Typescript strict mode, you won’t see this error. In this case, you should also use the readonly keyword to make sure that the value is never set directly.</p><pre>- username = signal(&#39;&#39;);<br>+ readonly username = signal(&#39;&#39;);</pre><p>Now Typescript will throw an error if you try to set the value directly.</p><pre>this.#userService.getUser().pipe(take(1)).subscribe(user =&gt; {<br>    // ❌ Cannot assign to &#39;username&#39; because it is a read-only property.<br>    // this.username = user.name;<br>    // ✅ To set the value you should use the set method <br>    this.username.set(user.name); <br>});</pre><p>Now, don’t forget to call this signal in the template in order to show the value.</p><pre>- &lt;div&gt;{{ username }}&lt;/div&gt;<br>+ &lt;div&gt;{{ username() }}&lt;/div&gt;</pre><p>And that’s it! You have removed the manual change detection call from your Angular application.</p><p>Why does this work? Well, signals will mark the template as dirty and as needed to be checked by Angular when they change, but also, in a zoneless world, they also trigger a Change Detection cycle which will update the view with the new value.</p><blockquote><em>Read more about it here: </em><a href="https://justangular.com/blog/a-new-era-for-angular-zoneless-change-detection"><em>A new era for Angular — Zoneless Change Detection</em></a></blockquote><p><em>I’m also looking to create an eslint rule that does all of this automatically for you, so you don’t have to do it manually. If you’re interested in this, let me know in the comments below.</em></p><h3>Thanks for reading!</h3><p>If this article was interesting and useful to you, and you want to learn more about Angular, support me by <a href="https://ko-fi.com/eneajahollari">buying me a coffee ☕️</a> or follow me on X (formerly Twitter) <a href="https://twitter.com/Enea_Jahollari">@Enea_Jahollari</a> where I tweet and blog a lot about Angular latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more. 💎</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=58dfa481deeb" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/removing-manual-change-detection-calls-from-my-angular-app-%EF%B8%8F-58dfa481deeb">Removing manual change detection calls from my Angular app ⚡️</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Protect your Angular app from infinite change detection loops ♾️]]></title>
            <link>https://itnext.io/protect-your-angular-app-from-infinite-change-detection-loops-%EF%B8%8F-da121430a2e1?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/da121430a2e1</guid>
            <category><![CDATA[signal]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[change-detection]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Sun, 24 Mar 2024 09:54:52 GMT</pubDate>
            <atom:updated>2024-03-28T19:43:14.657Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oYYwdP5J0op79TRdR0nW4w.jpeg" /></figure><p>Lately, Angular introduced signals, that are wonderfully powerful and greatly simplify the way we write Angular applications.</p><p>When working with signals in Angular, we know that Angular will make sure to always update the view when a signal is changed.</p><pre>@Component({<br>  template: `<br>    &lt;div&gt;{{ count() }}&lt;/div&gt;<br>    &lt;button (click)=&quot;increment()&quot;&gt;Increment&lt;/button&gt;<br>  `<br>})<br>export class AppComponent {<br>  count = signal(0);<br><br>  increment() {<br>    this.count.update(x =&gt; x + 1);<br>  }<br>}</pre><p>One other thing Angular has introduced is the afterRender lifecycle hook. This hook is called after Angular has rendered the view, which is a great place to do some work that should be done after the view has been updated.</p><pre>@Component()<br>export class AppComponent {<br>  count = signal(0);<br>  <br>  constructor() {<br>    afterRender(() =&gt; {<br>      console.log(&#39;View has been updated&#39;);<br>    });<br>  }<br>}</pre><p>If for some reason you need to update the view in the afterRender hook, and to do that you&#39;re updating a signal (which may have been called in the component&#39;s template), please make sure to not update the signal in an non-definitive way.</p><pre>@Component({<br>  template: `<br>    &lt;div&gt;{{ count() }}&lt;/div&gt;<br>  `<br>})<br>export class AppComponent {<br>  count = signal(0);<br>  <br>  constructor() {<br>    afterRender(() =&gt; {<br>      // This will cause an infinite change detection loop<br>      this.count.update(x =&gt; x + 1);<br>    });<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*JfUwTU17vXVsLlWt.png" /></figure><p>If you update a signal in the afterRender hook, make sure to update it in a definitive way. This means that the signal should be updated in a way that it will not change the value of the signal when the view is updated.</p><pre>@Component({<br>  template: `<br>    &lt;div&gt;{{ count() }}&lt;/div&gt;<br>  `<br>})<br>export class AppComponent {<br>  count = signal(0);<br>  <br>  constructor() {<br>    afterRender(() =&gt; {<br>      // This will not cause an infinite change detection loop<br>      this.count.set(/* new value */); <br>    });<br>  }<br>}</pre><p>By following this simple rule, you can protect your Angular app from infinite change detection loops.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=da121430a2e1" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/protect-your-angular-app-from-infinite-change-detection-loops-%EF%B8%8F-da121430a2e1">Protect your Angular app from infinite change detection loops ♾️</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Migrating from Custom Lazy Loading components to defer block]]></title>
            <link>https://itnext.io/migrating-from-custom-lazy-loading-components-to-defer-block-153e1b91ad95?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/153e1b91ad95</guid>
            <category><![CDATA[lazy-loading-in-angular]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[defer]]></category>
            <category><![CDATA[performance]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Mon, 11 Mar 2024 12:22:30 GMT</pubDate>
            <atom:updated>2024-03-11T12:30:41.101Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xE2PFC8WL-pzVMAmn4F4Bw.png" /><figcaption>Photo by <a href="https://unsplash.com/@priscilladupreez?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Priscilla Du Preez 🇨🇦</a> on <a href="https://unsplash.com/photos/black-pug-puppy-on-brown-wooden-chair-dOnEFhQ7ojs?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>Lazy loading components in Angular has not been an easy task for a long time. We had to go over `ngComponentOutlet` and dynamic imports and also handle different kind of events to load the desired component.</p><h4><strong>Example in the </strong><a href="https://github.com/tastejs/angular-movies"><strong>Movies</strong></a><strong> app</strong></h4><p>In the movies app we have an example in the `app-shell.component.ts` where we lazy load an account menu component when the user clicks on the account button.</p><pre>&lt;div class=&quot;account-menu-dropdown&quot;&gt;<br>  &lt;button <br>    type=&quot;button&quot; <br>    class=&quot;profile-button&quot; <br>    (mouseenter)=&quot;ui.loadAccountMenu()&quot;&gt;<br>      &lt;div class=&quot;focus-overlay&quot;&gt;&lt;/div&gt;<br>      &lt;fast-svg name=&quot;account&quot; /&gt;<br>  &lt;/button&gt;<br>  &lt;div class=&quot;profile-menu-content&quot;&gt;<br>    &lt;ng-container <br>        *rxLet=&quot;accountMenuComponent$; suspense: loading&quot; <br>        [lazy]=&quot;accountMenuComponent$&quot; /&gt;<br>    &lt;ng-template #loading&gt; Loading...&lt;/ng-template&gt;<br>  &lt;/div&gt;<br>&lt;/div&gt;</pre><pre>type Actions = {<br>  ...<br>  loadAccountMenu: void;<br>};<br><br>export class AppShellComponent {<br>  readonly ui = rxActions&lt;{ loadAccountMenu: void }&gt;();<br><br>  accountMenuComponent$ = this.ui.loadAccountMenu$.pipe(<br>    switchMap(() =&gt;<br>      import(&#39;./account-menu/account-menu.component&#39;).then((x) =&gt; x.default)<br>    ),<br>    shareReplay(1)<br>  );<br>}</pre><p>So, we create an `<strong>ui</strong>` actions object and we have a `<strong>loadAccountMenu</strong>` action that we call when the user clicks on the account button.</p><p>We have a `<strong>accountMenuComponent$</strong>` observable that we use to lazy load the `<strong>AccountMenuComponent</strong>` when the user clicks on the account button.</p><p>The observable is then used in the `<strong>*rxLet</strong>` directive to render the `<strong>AccountMenuComponent</strong>` when it’s loaded.</p><h4><strong>Migrating to defer block</strong></h4><p>Defer block is a new feature in Angular that allows us to defer the rendering of a component until it’s loaded.</p><p>We can use the `<strong>defer</strong>` block to achieve the same result as the previous example.</p><pre>&lt;div class=&quot;account-menu-dropdown&quot;&gt;<br>  &lt;button #accountButton type=&quot;button&quot; class=&quot;profile-button&quot;&gt;<br>    &lt;div class=&quot;focus-overlay&quot;&gt;&lt;/div&gt;<br>    &lt;fast-svg name=&quot;account&quot; /&gt;<br>  &lt;/button&gt;<br>  &lt;div class=&quot;profile-menu-content&quot;&gt;<br>    @defer (on hover(accountButton)) {<br>        &lt;app-account-menu /&gt;<br>    } @placeholder {<br>        Loading...<br>    }<br>  &lt;/div&gt;<br>&lt;/div&gt;</pre><p>That’s it. We don’t need to use any observables or actions, or register any listeners to load the `<strong>AccountMenuComponent</strong>`. We can safely remove the observable, the<strong> *rxLet </strong>directive and the actions object.</p><p>The `<strong>on hover()</strong>` will register an event listener on the `<strong>accountButton</strong>` and when the user hovers over the button, the `AccountMenuComponent` will be loaded and rendered.</p><p>More info in the <a href="https://angular.dev/guide/defer#on-hover">defer block docs</a>.</p><h3>Thanks for reading!</h3><p>If this article was interesting and useful to you, and you want to learn more about Angular, support me by <a href="https://ko-fi.com/eneajahollari">buying me a coffee</a> ☕️ or follow me on X (formerly Twitter) <a href="https://twitter.com/Enea_Jahollari">@Enea_Jahollari</a> where I tweet and blog a lot about <strong>Angular</strong> latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more. 💎</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=153e1b91ad95" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/migrating-from-custom-lazy-loading-components-to-defer-block-153e1b91ad95">Migrating from Custom Lazy Loading components to defer block</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Creating reusable Router Signals APIs in Angular ️]]></title>
            <link>https://itnext.io/creating-reusable-router-signals-apis-in-angular-%EF%B8%8F-6c4411b35e2a?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/6c4411b35e2a</guid>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[router]]></category>
            <category><![CDATA[observables]]></category>
            <category><![CDATA[signal]]></category>
            <category><![CDATA[rxjs]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Wed, 07 Feb 2024 22:15:08 GMT</pubDate>
            <atom:updated>2024-02-09T09:06:20.368Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v9z3jv45QFCgcr6C9z9Fvg.png" /><figcaption>Photo by <a href="https://unsplash.com/@whatyouhide?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Andrea Leopardi</a> on <a href="https://unsplash.com/photos/person-running-on-road-at-daytime-QVD3Xht9txA?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>Building single-page applications with Angular often involves working with the Angular Router.</p><p>When working with the router there are a few common patterns that we often find ourselves repeating.</p><p>For example, we often need to grab the current route params or query params and use them in our components.</p><pre>@Component({<br>  template: `<br>    &lt;h1&gt;Product Details&lt;/h1&gt;<br>    &lt;p&gt;{{ productName }}&lt;/p&gt;<br>  `<br>})<br>export class ProductDetails {<br>  private route = inject(ActivatedRoute);<br>  private productsService = inject(ProductsService);<br><br>  productName: string = &#39;&#39;;<br><br>  ngOnInit() {<br>    const prodcutId = this.route.snapshot.params[&#39;id&#39;];<br><br>    this.productsService.getProduct(prodcutId)<br>    .pipe(take(1))<br>    .subscribe(product =&gt; {<br>      this.productName = product.name;<br>    });<br>  }<br>}</pre><p>In the above example, we are using the `<strong>ActivatedRoute</strong>` to grab the current route params and then using the `<strong>ProductsService</strong>` to fetch the product details.</p><p>The issue with the above code is that when the route params change, the component will not update the `<strong>productName</strong>` value. Let’s fix that.</p><p>Let’s make this more declarative and reactive using observables.</p><h4><strong>Using Observables to react to route changes</strong></h4><p>Just like we used the snapshot to grab the route params, we can use the `<strong>params</strong>` observable to listen to route params changes.</p><pre>@Component({<br>  template: `<br>    &lt;h1&gt;Product Details&lt;/h1&gt;<br>    &lt;p&gt;{{ productName$ | async }}&lt;/p&gt;<br>  `<br>})<br>export class ProductDetails {<br>  private route = inject(ActivatedRoute);<br>  private productsService = inject(ProductsService);<br><br>  // Store the productId observable<br>  productId$ = this.route.params.pipe(map(params =&gt; params[&#39;id&#39;]));<br><br>  productName$ = this.productId$.pipe(<br>    // Fetch the product details when the productId changes<br>    // and cancel the previous request<br>    switchMap(id =&gt; this.productsService.getProduct(id)),<br>    map(product =&gt; product.name)<br>  );<br>}</pre><p>Here we have a declarative and reactive way to fetch the product details when the route params change using observables, that will also cancel the previous request when the route params change (this is useful when the user is navigating quickly between routes).</p><p>We are using the `<strong>async</strong>` pipe to subscribe to the `<strong>productName$</strong>` observable and display the product name in the template.</p><h4><strong>Refactoring to Signals</strong></h4><p>We can take this a step further and refactor the observables into signals. Let’s use the `<strong>toSignal</strong>` function to convert the observables into signals.</p><pre>@Component({<br>  template: `<br>    &lt;h1&gt;Product Details&lt;/h1&gt;<br>    &lt;p&gt;{{ productName() }}&lt;/p&gt; &lt;!-- No need for async pipe --&gt;<br>  `<br>})<br>export class ProductDetails {<br>  private route = inject(ActivatedRoute);<br>  private productsService = inject(ProductsService);<br><br>  productId$ = this.route.params.pipe(map(params =&gt; params[&#39;id&#39;]));<br><br>  productName$ = this.productId$.pipe(<br>    switchMap(id =&gt; this.productsService.getProduct(id)),<br>    map(product =&gt; product.name)<br>  );<br><br>  // This will convert the productName$ observable into a signal <br>  // and will be updated when the productName$ observable emits a new value<br>  productName = toSignal(this.productName$, { initialValue: &#39;&#39; });<br>}</pre><p>Now we have a `<strong>productName</strong>` signal that will be updated when the `<strong>productName$</strong>` observable emits a new value. This is great! We can now use the `<strong>productName</strong>` signal in our template without the need for the `<strong>async</strong>` pipe.</p><p>Can we do better? To, write less code maybe?</p><h4><strong>Creating a reusable router signals API</strong></h4><p>We can create a reusable router signals API that will allow us to easily grab the current route params and query params and use them in a declarative way using signals.</p><p>We want to be able to inject params that should return us all the route params as a signal, and if we pass a key, it should return us the value of that key as a signal.</p><p>Something like this:</p><pre>export class ProductDetails {<br>  params = injectParams(); // Signal&lt;Params&gt;<br>  productId = injectParams(&#39;id&#39;); // Signal&lt;string | null&gt;<br><br>  private productsService = inject(ProductsService);<br><br>  // usage with computedAsync function<br>  productName = computedAsync(() =&gt; <br>    this.productsService.getProduct(this.productId()).pipe(map(p =&gt; p.name))<br>  );<br>}</pre><p>More info about `<strong>computedAsync</strong>` can be found in the <a href="https://ngxtension.netlify.app/utilities/signals/computed-async/">docs</a>.</p><p>I wrote more about it here:</p><p><a href="https://itnext.io/building-computedasync-for-signals-in-angular-501246c9b7ea">Building ComputedAsync for Signals in Angular</a></p><h4><strong>Implementing the injectParams function</strong></h4><p>Because our function will inject the `<strong>ActivatedRoute</strong>` we need to make sure we are in an injection context. We can use the `<strong>assertInInjectionContext</strong>` function to do that.</p><pre>export function injectParams(): Signal&lt;Params&gt; {<br>  assertInInjectionContext(injectParams);<br>  const route = inject(ActivatedRoute);<br>}</pre><p>Now that we have access to the `<strong>ActivatedRoute</strong>` we can grab the route params and convert them into a signal using the `<strong>toSignal</strong>` function.</p><pre>export function injectParams(): Signal&lt;Params&gt; {<br>  assertInInjectionContext(injectParams);<br>  const route = inject(ActivatedRoute);<br>+  return toSignal(route.params);<br>}</pre><p>Params emit synchronously, so to enforce it, let’s use `<strong>toSignal</strong>` with `<strong>requireSync</strong>` option.</p><pre>export function injectParams(): Signal&lt;Params&gt; {<br>  assertInInjectionContext(injectParams);<br>  const route = inject(ActivatedRoute);<br>+  return toSignal(route.params, { requireSync: true });<br>}</pre><p>We can also add support for passing a key to the `<strong>injectParams</strong>` function. If a key is passed, we should return the value of that key as a signal.</p><pre>export function injectParams&lt;T&gt;(<br>+  key?: string // Include the optional key parameter<br>): Signal&lt;Params | string | null&gt; {<br>  assertInInjectionContext(injectParams);<br>  const route = inject(ActivatedRoute);<br>  // Create a helper function to grab the value of the key<br>+  const getParam = (params: Params) =&gt; key ? params?.[key] ?? null : params;<br>  // We need to map the params observable to the value of the key<br>-  return toSignal(route.params, { requireSync: true });<br>+  return toSignal(route.params.pipe(map(getParam)), { requireSync: true });<br>}</pre><p>We can extend the `<strong>injectParams</strong>` function to also support a transform function that will allow us to transform the params into a different value.</p><p>It will be used like this:</p><pre>export class ProductDetails {<br>  // example of using a transform function<br>  allParamKeys = injectParams(params =&gt; Object.keys(params));<br>}</pre><p>While we add the support for the transform function, we can also make the function generic to support the return type of the transform function.</p><pre>export function injectParams&lt;T&gt;(<br> keyOrTransform?: string | ((params: Params) =&gt; T),<br>): Signal&lt;T | Params | string | null&gt; {<br>  assertInInjectionContext(injectParams);<br>  const route = inject(ActivatedRoute);<br> <br>  if (typeof keyOrTransform === &#39;function&#39;) {<br>    return toSignal(route.params.pipe(map(keyOrTransform)), { requireSync: true });<br>  }<br><br>  const getParam = (params: Params) =&gt;<br>    keyOrTransform ? params?.[keyOrTransform] ?? null : params;<br><br>  return toSignal(route.params.pipe(map(getParam)), { requireSync: true });<br>}</pre><p>As we can see, we have created a reusable router signals API that will allow us to easily grab the current route params and use them in a declarative way using signals.</p><p>We can do the same for the query params using the `<strong>queryParams</strong>` observable from the `<strong>ActivatedRoute</strong>`.</p><p>But, you don’t need to do that, because it’s already done for you in the `<strong>ngxtension</strong>` library.</p><h4><strong>`injectQueryParams` and `injectParams`</strong></h4><p>These two functions are already published by the `<strong>ngxtension</strong>` library</p><p>- <a href="https://ngxtension.netlify.app/utilities/injectors/inject-params/">injectParams</a></p><p>- <a href="https://ngxtension.netlify.app/utilities/injectors/inject-query-params/">injectQueryParams</a></p><p>They are fully tested and are already being used in multiple projects.</p><h4><strong>Using `withComponentInputBinding()` with signal inputs</strong></h4><p>In v17.1 Angular introduced signal inputs, and before that introduced the `withComponentInputBinding()` function which enables us to have inputs with the same name as our params or query params.</p><p>I wrote about that function here:</p><p><a href="https://itnext.io/bind-route-info-to-component-inputs-new-router-feature-1d747e559dc4">Bind Route Info to Component Inputs (New Router feature)</a></p><p>What’s the difference between these functions and signal inputs? Two things:</p><ul><li><strong>Being explicit about where your data comes from</strong></li></ul><p>If you have an input called productId, do you expect it to come from a parent component or the route params?</p><pre>export class ProductDetails {<br>  // where does this come from?<br>  productId = input&lt;string&gt;(); <br><br>  // being explicit we are getting a route param<br>  productId = injectParams(&#39;id&#39;); <br><br>  private productsService = inject(ProductsService);<br><br>  // we can use computedAsync with both ways btw.<br>  productName = computedAsync(() =&gt; <br>    this.productsService.getProduct(this.productId()).pipe(map(p =&gt; p.name))<br>  ); <br>}</pre><ul><li><strong>What if you need all the params (or query params)</strong></li></ul><p>We cannot grab all the params and queryParams using inputs, so we still have to rely on injecting `<strong>ActivatedRoute</strong>` and listen to observable changes. And that’s something `<strong>injectParams</strong>` solves by default.</p><pre>export class AllProducts {<br>  private productsService = inject(ProductsService);<br>  private productsFilters = injectParams(p =&gt; paramsToFilters(p));<br><br>  allProducts = computedAsync(() =&gt; <br>    this.productsService.getProducts(this.productsFilters()))<br>  );<br>}<br><br>function paramsToFilters(params: Params): ProductsFilters {<br>  return ...;<br>}</pre><p>That’s all folks! Hope you liked it!</p><h3>Thanks for reading!</h3><p>If this article was interesting and useful to you, and you want to learn more about Angular, support me by <a href="https://ko-fi.com/eneajahollari">buying me a coffee</a> ☕️ or follow me on X (formerly Twitter) <a href="https://twitter.com/Enea_Jahollari">@Enea_Jahollari</a> where I tweet and blog a lot about <strong>Angular</strong> latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more. 💎</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6c4411b35e2a" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/creating-reusable-router-signals-apis-in-angular-%EF%B8%8F-6c4411b35e2a">Creating reusable Router Signals APIs in Angular 🗺️</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building ComputedAsync for Signals in Angular]]></title>
            <link>https://itnext.io/building-computedasync-for-signals-in-angular-501246c9b7ea?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/501246c9b7ea</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[signal]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Mon, 22 Jan 2024 16:07:43 GMT</pubDate>
            <atom:updated>2024-01-22T16:46:23.873Z</atom:updated>
            <content:encoded><![CDATA[<h4>Handling async operations using Signals and Rxjs in Angular</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5VWlo3nw7OMfVpKm7HL9RA.png" /><figcaption>Photo by <a href="https://unsplash.com/@tuannguyenminh?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Tuân Nguyễn Minh</a> on <a href="https://unsplash.com/photos/closeup-photo-of-red-petaled-flower-field-pGr7g4l8EOI?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><h4><strong>A little bit of history</strong></h4><p>Handling async operations in Angular has always been the job of Observables. Observables are a great way to handle async operations. But with the introduction of Signals in Angular, everyone is trying to use Signals for everything, but Signals are not meant to handle async operations. Signals are meant to handle value and not events. So, how do we handle async operations using Signals? Let’s find out.</p><h4><strong>Motivation</strong></h4><p>I will use a simple example for an API call. Let’s say we have a component that calls an API and displays the data. We will use the `<strong>HttpClient</strong>` to make the API call. The `<strong>HttpClient</strong>` returns an `<strong>Observable</strong>` which we can subscribe to and get the data. Let’s see how we can do this using Signals.</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br><br>  user = input.required&lt;User&gt;();<br><br>  favoriteImages = signal&lt;string[]&gt;([]);<br><br>  constructor() {<br>    effect(() =&gt; {<br>      this.imagesService.getImages(this.user().favoriteImages).subscribe(images =&gt; {<br>        this.favoriteImages.set(images);<br>      });<br>    });<br>  }<br>}</pre><p>As you can see, I’m also using signal inputs to use the built-in reactivity.</p><p>But, we don’t handle the unsubscribe part. So, we need to do that manually. The effect function includes a callback function that is called every time the effect runs. We can use that to unsubscribe from the subscription.</p><p>This is how we can do it.</p><pre>export class UserComponent {<br>  constructor() {<br>    // onCleanup is a callback function that is called everytime the effect runs<br>    effect((onCleanup) =&gt; { <br>      const sub = this.imagesService.getImages(this.user().favoriteImages).subscribe(images =&gt; {<br>        this.favoriteImages.set(images);<br>      });<br>      onCleanup(() =&gt; sub.unsubscribe()) // unsubscribe from the subscription<br>    });<br>  }<br>}</pre><p>To sum up, here’s what’s happening in the above code:</p><ul><li>We register an effect that will run whenever the `<strong>user</strong>` input changes.</li><li>The effect runs at least once by default, so it will make that initial API call.</li><li>The effect will run again whenever the `<strong>user</strong>` input changes.</li><li>Every time the effect re-runs, the <strong>onCleanup</strong> function will call the callback function passed to it.</li><li>Our callback function will unsubscribe from the previous subscription. (So, it will behave like the `<strong>switchMap</strong>` operator in RxJS)</li><li>When the API call returns, we set the value of the `<strong>favoriteImages</strong>` signal.</li></ul><h4><strong>Problem</strong></h4><p>What we are trying to do in the above example is to have some derived state based on the user `favoriteImages` ids. So, using an effect may not be the straightforward way to do this, or we may forget to unsubscribe from our subscription.</p><p>One other solution is to use `<strong>toObservable</strong>` helper function.</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br><br>  user = input.required&lt;User&gt;();<br><br>  favoriteImages = toSignal(toObservable(this.user).pipe(<br>    switchMap(user =&gt; this.imagesService.getImages(user.favoriteImages))<br>  ), { initialValue: [] });<br>}</pre><p>This is a better solution, but it’s not perfect. What happens if we include some other input and we need to include it in our API call? We will have to use `<strong>combineLatest</strong>` operator.</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br><br>  user = input.required&lt;User&gt;();<br>  otherInput = input.required&lt;string&gt;();<br><br>  favoriteImages = toSignal(combineLatest([<br>    toObservable(this.user),<br>    toObservable(this.otherInput)<br>  ]).pipe(<br>    switchMap(([user, otherInput]) =&gt; this.imagesService.getImages(user.favoriteImages, otherInput))<br>  ), { initialValue: [] });<br>}</pre><p>This gets messy very quickly! Because we start to include more and more rxjs operators, and we have to use `<strong>toObservable</strong>` and `<strong>toSignal</strong>` everywhere.</p><p>We can do better!</p><h3><strong>Building ComputedAsync</strong></h3><p>We want our `<strong>computedAsync</strong>` function to behave like the `<strong>computed</strong>` function, but it should handle async operations. Basically, it should return a signal that will have the value of the async operation.</p><pre>favoriteImages = computedAsync(() =&gt; <br>  this.imagesService.getImages(this.user().favoriteImages)<br>);</pre><p>We want to return an observable (or promise), and we want the `<strong>computedAsync</strong>` function to handle the subscription and unsubscribe from it.</p><h4><strong>Handling the callback function</strong></h4><p>We want the developer to be able to pass either an observable or a promise, or just normal value. So, we need to handle all of these cases.</p><p>Here are the possible cases:</p><pre>type ComputationResult&lt;T&gt; = Promise&lt;T&gt; | Observable&lt;T&gt; | T | undefined;</pre><p>We want to accept a callback fn and return a Signal. So, we need to accept a callback function that will return a `<strong>ComputationResult&lt;T&gt;</strong>`.</p><pre>export function computedAsync&lt;T&gt;(<br>    computation: () =&gt; ComputationResult&lt;T&gt;<br>): Signal&lt;T&gt; {<br>  // ...<br>}</pre><h4><strong>Handling the current value and the result</strong></h4><p>We need to handle the current value and to return the result of the computation. We can use a `<strong>WritableSignal</strong>` to handle the current value and a computed signal to return the result of the computation.</p><pre>export function computedAsync&lt;T&gt;(<br>    computation: () =&gt; ComputationResult&lt;T&gt;<br>): Signal&lt;T&gt; {<br>  const sourceValue = signal&lt;T | undefined&gt;(undefined);<br>  return computed(() =&gt; sourceValue()!);<br>}</pre><h4><strong>Handling the computation</strong></h4><p>Because the computation will include signals, and the only way to listen to signal changes is by using `<strong>effect</strong>`, we need to use `<strong>effect</strong>` to handle the computation.</p><pre>import { isObservable } from &#39;rxjs&#39;;<br><br>export function computedAsync&lt;T&gt;(<br>    computation: () =&gt; ComputationResult&lt;T&gt;<br>): Signal&lt;T&gt; {<br>  const sourceValue = signal&lt;T | undefined&gt;(undefined);<br><br>  effect(() =&gt; {<br>    const value = computation(); // store the result of the computation<br><br>    // handle the result if it&#39;s an observable or a promise or a normal value<br>    if (isObservable(value) || isPromise(value)) {<br>      // TODO: handle observable and promise<br>    } else {<br>      // TODO: handle normal value<br>    }<br>  });<br><br>  return computed(() =&gt; sourceValue()!);<br>}<br><br>// helper function to check if the value is a promise<br>function isPromise&lt;T&gt;(value: any): value is Promise&lt;T&gt; {<br> return value &amp;&amp; typeof value.then === &#39;function&#39;;<br>}</pre><p>But, `<strong>effect</strong>` depends on the `<strong>DestroyRef</strong>` token, so it needs to be in an injection context, or we need to pass an injector to it. Let’s handle that.</p><h4><strong>Handling injection context</strong></h4><p>I will use the <a href="https://ngxtension.netlify.app/utilities/injectors/assert-injector/">assertInjector</a> helper function (created by <a href="https://twitter.com/Nartc1410">Chau Tran</a>) provided in the `<strong>ngxtension</strong>` library.</p><p>The `<strong>assertInjector</strong>` function will check if the injector is provided, and if it’s not, it will throw an error. In the third argument, we can pass a callback function that will be called in the injection context.</p><p>Let’s create a `<strong>ComputedAsyncOptions</strong>` interface that will include the injector and the equal function (that the normal `<strong>computed</strong>` function also includes).</p><pre>interface ComputedAsyncOptions&lt;T&gt; extends CreateComputedOptions&lt;T&gt; {<br> injector?: Injector;<br>}</pre><p>Now, we can use the `<strong>assertInjector</strong>` function.</p><pre>export function computedAsync&lt;T&gt;(<br>    computation: () =&gt; ComputationResult&lt;T&gt;,<br>    options?: ComputedAsyncOptions&lt;T&gt;<br>): Signal&lt;T&gt; {<br>  return assertInjector(computedAsync, options?.injector, () =&gt; {<br>    // here we can safely use effect and inject function because we are in an injection context<br>     effect(() =&gt; { /* ...  */ }, { injector: options?.injector });<br>  });<br>}</pre><h4><strong>Handling the subscription</strong></h4><p>Just like we have a `<strong>sourceValue</strong>` signal to handle the current value, we need a `<strong>sourceEvent$</strong>` observable to handle the subscription. We will use a `<strong>Subject</strong>` to handle the subscription.</p><p>We want our value of the `<strong>sourceEvent$</strong>` to be either a promise or an observable.</p><pre>const sourceEvent$ = new Subject&lt;Promise&lt;T&gt; | Observable&lt;T&gt;&gt;();</pre><p>Let’s subscribe to the `<strong>sourceEvent$</strong>` and set the value of the `<strong>sourceValue</strong>` signal.</p><p>We also have to take care of flattening the observable, because we will pass an observable or promise to our `<strong>sourceEvent$</strong>`.</p><p>That’s why we will use `<strong>switchMap</strong>` operator to flatten the observable.</p><blockquote>As a side effect, `switchMap` will also unsubscribe from the previous subscription 🎉.</blockquote><pre>const sourceResult = sourceEvent$<br>    .pipe(switchMap(s$ =&gt; s$))<br>    .subscribe({<br>        // set the value of the sourceValue signal when the source$ emits a value<br>        next: (value) =&gt; sourceValue.set(value),<br>        error: (error) =&gt; {<br>            // NOTE: Error should be handled by the user (using catchError or .catch())<br>            sourceValue.set(error);<br>        }<br>    });</pre><p>Having `<strong>switchMap(s$ =&gt; s$)</strong>` can be replaced with `<strong>switchAll()</strong>` operator.</p><p>Thanks to <a href="https://github.com/hoc081098">Petrus Nguyễn Thái Học</a> and <a href="https://github.com/LcsGa">Lucas Garcia</a> for pointing that out.</p><pre>const sourceResult = sourceEvent$<br>    .pipe(switchAll())<br>    .subscribe();</pre><h4><strong>Handling the subscription cleanup</strong></h4><p>Because we subscribed to the `<strong>sourceEvent$</strong>` observable, we need to unsubscribe from it. We can use the `<strong>DestroyRef</strong>` token to handle that. `<strong>DestroyRef</strong>` has an `<strong>onDestroy</strong>` method that will call the callback function passed to it when the current injection context is destroyed, in our case, when the component is destroyed.</p><pre>export function computedAsync&lt;T&gt;(<br>    computation: () =&gt; ComputationResult&lt;T&gt;,<br>    options?: ComputedAsyncOptions&lt;T&gt;<br>): Signal&lt;T&gt; {<br>  return assertInjector(computedAsync, options?.injector, () =&gt; {<br>    const destroyRef = inject(DestroyRef);<br><br> const sourceEvent$ = new Subject&lt;Promise&lt;T&gt; | Observable&lt;T&gt;&gt;();<br><br>    effect(() =&gt; { /* ...  */ });<br><br>    const sourceResult = source$.subscribe(/* ... */);<br><br>    destroyRef.onDestroy(() =&gt; {<br>      sourceResultSubcription.unsubscribe();<br>    });<br>  });<br>}</pre><p>That’s it! We subscribe to get the value and we unsubscribe when the component is destroyed.</p><h4><strong>Handling the returned observable or promise in the computation</strong></h4><p>This is currently how `<strong>computedAsync</strong>` looks like:</p><pre>export function computedAsync&lt;T&gt;(<br>    computation: () =&gt; ComputationResult&lt;T&gt;,<br>    options?: ComputedAsyncOptions&lt;T&gt;<br>): Signal&lt;T&gt; {<br>  return assertInjector(computedAsync, options?.injector, () =&gt; {<br>    const destroyRef = inject(DestroyRef);<br><br>    const sourceValue = signal&lt;T | undefined&gt;(undefined);<br><br> const sourceEvent$ = new Subject&lt;Promise&lt;T&gt; | Observable&lt;T&gt;&gt;();<br><br>    effect(() =&gt; {<br>        const value = computation(); // store the result of the computation<br><br>        // handle the result if it&#39;s an observable or a promise or a normal value<br>        if (isObservable(value) || isPromise(value)) {<br>            // TODO: handle observable and promise<br>        } else {<br>            // TODO: handle normal value<br>        }<br>    });<br><br>    const sourceResult = sourceEvent$<br>        .pipe(switchAll())<br>        .subscribe({<br>            next: (value) =&gt; sourceValue.set(value),<br>            error: (error) =&gt; sourceValue.set(error)<br>        });<br><br>    destroyRef.onDestroy(() =&gt; {<br>      sourceResultSubcription.unsubscribe();<br>    });<br><br>    return computed(() =&gt; sourceValue()!);<br>  });<br>}</pre><p>Let’s handle the TODOs in the above code.</p><p>First, let’s handle the normal value case. We just need to set the value of the `<strong>sourceValue</strong>` signal.</p><pre>effect(() =&gt; {<br>  const value = computation(); // store the result of the computation<br><br>  // handle the result if it&#39;s an observable or a promise or a normal value<br>  if (isObservable(value) || isPromise(value)) {<br>      // TODO: handle observable and promise<br>  } else {<br>      sourceValue.set(value);<br>  }<br>});</pre><p>This will throw an error, because we cannot set the value of a signal inside an effect, without first enabling it for the effect.</p><pre>effect(() =&gt; {<br>    // ...<br>}, { allowSignalWrites: true }) // enable signal writes</pre><p>But, there’s another way to solve this problem. We can use the `<strong>untracked</strong>` function to set the value of the signal without enabling it for the effect (this is basically doing the same thing as the above code). Read more about this trick <a href="https://github.com/angular/angular/issues/53986">here</a>.</p><p>Let’s use it:</p><pre>untracked(() =&gt; sourceValue.set(value));</pre><p>Let’s handle the observable and promise case. Just like we set the value in the signal, we need to `<strong>next</strong>` to the `<strong>sourceEvent$</strong>` observable.</p><pre>effect(() =&gt; {<br>    const value = computation(); // store the result of the computation<br><br>    // handle the result if it&#39;s an observable or a promise or a normal value<br>    if (isObservable(value) || isPromise(value)) {<br>        sourceEvent$.next(value);<br>    } else {<br>        untracked(() =&gt; sourceValue.set(value));<br>    }<br>});</pre><p>This may cause some issues, if we just leave it like that. How so?</p><p>Look at this example:</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user = input.required&lt;User&gt;();<br><br>  someValue = signal&lt;string&gt;(&#39;&#39;);<br><br>  favoriteImages = computedAsync(() =&gt; {<br>    return this.imagesService.getImages(this.user().favoriteImages).pipe(<br>       tap(() =&gt; this.someValue.set(&#39;some value&#39;))<br>    );<br>  });<br>}</pre><p>The `<strong>someValue</strong>` signal will be set inside our computation, but our computation is inside an effect, basically, we are setting the value of a signal inside an effect. This will throw an error. So, we need to <strong>untrack</strong> the `<strong>sourceEvent$.next()</strong>`.</p><pre>effect(() =&gt; {<br>    const value = computation(); // store the result of the computation<br><br>    // handle the result if it&#39;s an observable or a promise or a normal value<br>    if (isObservable(value) || isPromise(value)) {<br>        untracked(() =&gt; sourceEvent$.next(value));<br>    } else {<br>        untracked(() =&gt; sourceValue.set(value));<br>    }<br>});</pre><p>And now, our `<strong>computedAsync</strong>` function is complete 🎉!</p><h4><strong>Initial value</strong></h4><p>By default, the initial value of the `<strong>sourceValue</strong>` signal is `<strong>undefined</strong>`. But, we can pass an initial value to the `<strong>computedAsync</strong>` function.</p><pre>interface ComputedAsyncOptions&lt;T&gt; extends CreateComputedOptions&lt;T&gt; {<br> initialValue?: T;<br> injector?: Injector;<br>}<br><br>export function computedAsync&lt;T&gt;(<br>    computation: () =&gt; ComputationResult&lt;T&gt;,<br>    options?: ComputedAsyncOptions&lt;T&gt;<br>): Signal&lt;T&gt; {<br>  return assertInjector(computedAsync, options?.injector, () =&gt; {<br>    // ...<br>    const sourceValue = signal&lt;T | undefined&gt;(options?.initialValue ?? undefined);<br>    // ...<br>  });<br>}</pre><p>Now, we can pass an initial value to the `<strong>computedAsync</strong>` function.</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user = input.required&lt;User&gt;();<br><br>  favoriteImages = computedAsync(() =&gt; {<br>    return this.imagesService.getImages(this.user().favoriteImages);<br>  }, { initialValue: [] });<br>}</pre><h4><strong>Handling race conditions (behavior)</strong></h4><p>Currently, we use only `<strong>switchAll</strong>` operator to handle the subscription and it will cancel the previous calls. But the devs may want to have a different behavior, and for this, we can add a `<strong>behavior</strong>` option to the `<strong>computedAsync</strong>` function.</p><pre>type ComputedAsyncBehavior = &#39;switch&#39; | &#39;merge&#39; | &#39;concat&#39; | &#39;exhaust&#39;;<br><br>interface ComputedAsyncOptions&lt;T&gt; extends CreateComputedOptions&lt;T&gt; {<br> initialValue?: T;<br> injector?: Injector;<br> behavior?: ComputedAsyncBehavior;<br>}</pre><p>We can use the `<strong>behavior</strong>` option to handle the subscription.</p><p>Let’s create a `<strong>createFlattenObservable</strong>` function that will handle the operator based on the `<strong>behavior</strong>` option.</p><pre>function createFlattenObservable&lt;T&gt;(<br> source: Subject&lt;Promise&lt;T&gt; | Observable&lt;T&gt;&gt;,<br> behavior: ComputedAsyncBehavior,<br>): Observable&lt;T&gt; {<br> const KEY_OPERATOR_MAP = {<br>  merge: mergeAll,<br>  concat: concatAll,<br>  exhaust: exhaustAll,<br>  switch: switchAll,<br> };<br><br> return source.pipe(KEY_OPERATOR_MAP[behavior]());<br>}</pre><p>Now, we can use the `<strong>createFlattenObservable</strong>` function to handle the subscription.</p><pre>const source$: Observable&lt;T&gt; = createFlattenObservable(<br>    sourceEvent$,<br>    options?.behavior ?? &#39;switch&#39;,<br>);</pre><p>By default, we use `<strong>switch</strong>` behavior, but we can pass a different behavior.</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user = input.required&lt;User&gt;();<br><br>  favoriteImages = computedAsync(() =&gt; <br>    this.imagesService.getImages(this.user().favoriteImages), <br>    { initialValue: [], behavior: &#39;merge&#39; }<br>  );<br>}</pre><p>Because rxjs operators also support Promises, we can pass a promise to the `<strong>sourceEvent$</strong>` and it will handle it, just like it handles observables.</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user = input.required&lt;User&gt;();<br><br>  favoriteImages = computedAsync(() =&gt; <br>    fetch(`https://localhost/api/images/${this.user().favoriteImages}`).then(res =&gt; res.json()), <br>    { initialValue: [], behavior: &#39;merge&#39; }<br>  );<br>}</pre><h4><strong>How to use the previous value in the computation?</strong></h4><p>Inside the effect, we can get the current value from the `<strong>sourceValue</strong>` signal. But, reading a signal inside an effect, registers it as a dependency. So, we need to <strong>untrack</strong> it first, then we can pass it to the `<strong>computation</strong>` function.</p><pre>effect(() =&gt; {<br>    const currentSourceValue = untracked(() =&gt; sourceValue());<br>    const value = computation(currentSourceValue); // store the result of the computation<br>    // ...  <br>}); </pre><p>This enables us to use the previous value in the computation.</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user = input.required&lt;User&gt;();<br><br>  favoriteImages = computedAsync((previousFavoriteImages) =&gt; {<br>      if (previousFavoriteImages) { /* do something */ }<br>      return this.imagesService.getImages(this.user().favoriteImages);<br>  }, <br>  { initialValue: [], behavior: &#39;merge&#39; });<br>}</pre><h3><strong>Use computedAsync from ngxtension</strong></h3><p>The `<strong>computedAsync</strong>` function is available in the `ngxtension` library.</p><pre>npm install ngxtension<br># or<br>yarn add ngxtension</pre><p>Then, you can import it from `<strong>ngxtension</strong>` library.</p><pre>import { computedAsync } from &#39;ngxtension/computed-async&#39;;</pre><p>And use it like this:</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user = input.required&lt;User&gt;();<br><br>  favoriteImages = computedAsync(() =&gt; <br>    this.imagesService.getImages(this.user().favoriteImages), <br>    { initialValue: [] }<br>  );<br>}</pre><p>📚 Documentation is available <a href="https://ngxtension.netlify.app/utilities/signals/computed-async/">here</a>.</p><p>🔨 Read more about the development of `<strong>computedAsync</strong>` <a href="https://github.com/nartc/ngxtension-platform/pull/229">here</a>.</p><h3>Thanks for reading!</h3><p>If this article was interesting and useful to you, and you want to learn more about Angular, support me by <a href="https://ko-fi.com/eneajahollari">buying me a coffee</a> ☕️ or follow me on X (formerly Twitter) <a href="https://twitter.com/Enea_Jahollari">@Enea_Jahollari</a> where I tweet and blog a lot about <strong>Angular</strong> latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more. 💎</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=501246c9b7ea" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/building-computedasync-for-signals-in-angular-501246c9b7ea">Building ComputedAsync for Signals in Angular</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Angular Signal Inputs are here to change the game ]]></title>
            <link>https://itnext.io/angular-signal-inputs-are-here-to-change-the-game-d0ec967b301f?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/d0ec967b301f</guid>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[putin]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[signal]]></category>
            <category><![CDATA[new-features]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Wed, 10 Jan 2024 14:41:38 GMT</pubDate>
            <atom:updated>2024-01-21T02:21:11.748Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*auBK3glHGq5WIZh8rXu5Og.png" /><figcaption>Photo by <a href="https://unsplash.com/@introspectivedsgn?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Erik Mclean</a> on <a href="https://unsplash.com/photos/persons-left-palm-about-to-catch-black-dice-C3T8KTZxTFM?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>Angular has gone through a lot of changes in the past few years. Since the release of 2.0 Angular embraced decorators and used them to annotate parts of code that should be processed by Angular. We have <strong>Component</strong>, <strong>Directive</strong>, <strong>Pipe</strong>, and <strong>Injectable</strong> decorators for classes, etc. We also have Input and Output decorators that are used to define the inputs and outputs of a component (public API of a component).</p><p>In this article, we will see how Angular is going to reduce the decorator usage for Inputs by using signal inputs and how it will make the code more readable, and easier to understand.</p><h3>Decorator Inputs</h3><p>Let’s start with a simple example of a component that has an input property.</p><pre>@Component({<br>  selector: &#39;user&#39;,<br>  template: `<br>      &lt;h1&gt;{{ user.name }}&lt;/h1&gt;<br>      &lt;p&gt;{{ user.email }}&lt;/p&gt;<br>  `,<br>})<br>export class UserComponent {<br>  @Input() user: User;<br>}</pre><p>The @Input decorator is used to define an input property. The <strong>user</strong> property is an input property and it is used to pass a <strong>User</strong> object to the component. The <strong>User</strong> object is then used to render the name and email of the user.</p><p>The code above looks ok, but it has a few issues 🤔.</p><p>Just by looking at the type, we can see that the <strong>user</strong> will always be set (it’s not optional). But, we’re still allowed to use the component as:</p><pre>&lt;user /&gt;</pre><p>However, this will result in an error at runtime because the <strong>user</strong> property is not set.</p><pre>Error: Cannot read property &#39;name&#39; of undefined</pre><p>We can fix this by making the `<strong>user</strong>` property optional:</p><pre>@Input() user?: User;</pre><p>Now, we need to check if the <strong>user</strong> is set before using it:</p><pre>@if (user) {<br>  &lt;h1&gt;{{ user.name }}&lt;/h1&gt;<br>  &lt;p&gt;{{ user.email }}&lt;/p&gt;<br>}</pre><p>or by using the<strong> ?</strong> operator:</p><pre>&lt;h1&gt;{{ user?.name }}&lt;/h1&gt;<br>&lt;p&gt;{{ user?.email }}&lt;/p&gt;</pre><p>This is a lot of code for something that should be simple. We can fix this by using a default value:</p><pre>@Input() user: User = { name: &#39;&#39;, email: &#39;&#39; };</pre><p>Now, we can use the `<strong>user</strong>` property without checking if it is set. But, what if the `<strong>user</strong>` object has a lot more fields? We would need to set all of them to a default value. This is not a good solution 🙃.</p><p>What we can do is to make the user input required if it’s a core part of the component. We can do this by using the `<strong>{ required: true }</strong>` option:</p><pre>@Input({ required: true }) user: User;</pre><p>This will make the `<strong>user</strong>` input required and we will get an error if we don’t set it.</p><pre>&lt;user /&gt;</pre><p>This will result in an error:</p><pre>Error: Required input &#39;user&#39; from component UserComponent must be specified.</pre><h4>How can we make these errors appear earlier?</h4><p>What we can do is enable `<strong>strictPropertyInitialization</strong>` in the `<strong>tsconfig.json</strong>` file. This will make the compiler check if all properties are initialized. The code below will result in an error:</p><pre>// error: Property &#39;user&#39; has no initializer and is not assigned in the constructor.<br>@Input() user: User; </pre><p>To fix this TS error, we either need to set a default value or just set it to `<strong>undefined</strong>` or `<strong>null</strong>`:</p><pre>@Input() user: User | undefined;<br>// or<br>@Input() user: User | null = null;<br>// or<br>@Input() user?: User;</pre><p>And then, just like before we need to check if the `<strong>user</strong>` is set before using it.</p><p>If we try to make the `<strong>user</strong>` input required, we will get the same error:</p><pre>// error: Property &#39;user&#39; has no initializer and is not definitely assigned in the constructor.<br>@Input({ required: true }) user: User; </pre><p>We can fix this by using the <strong>! </strong>operator:</p><pre>@Input({ required: true }) user!: User;</pre><p>This is fine because we’re telling the compiler that the `<strong>user</strong>` property will be set before we use it.</p><h3>Signal Inputs</h3><p>In Angular v17.1, a new feature will be introduced —<strong> Signal Inputs</strong>. This is how they will look like:</p><pre>export class UserComponent {<br>  user = input&lt;User&gt;();<br>}</pre><p>The code above is equivalent to the code below:</p><pre>export class UserComponent {<br>  @Input() user: User | undefined;<br>}</pre><p>The difference is that by default if we don’t make the <em>input required</em>, the `<strong>user</strong>` property will be set to `<strong>undefined</strong>`. This is the first thing that signal inputs protect us from ✨.</p><h4>Required Inputs</h4><p>If we want to make the `<strong>user</strong>` input required, we can do it by using the `<strong>required</strong>` option:</p><pre>export class UserComponent {<br>  user = input.required&lt;User&gt;();<br>}</pre><p>This is equivalent to:</p><pre>export class UserComponent {<br>  @Input({ required: true }) user!: User;<br>}</pre><p>What we can also do is to set a default value:</p><pre>export class UserComponent {<br>  user = input&lt;User&gt;({ name: &#39;&#39;, email: &#39;&#39; });<br>}</pre><blockquote>Because the user will always be instantiated, we won’t need to use the ! (non null assertion) anymore 🚀</blockquote><p>As we can see, we don’t have to fight with Angular typings and Typescript anymore or have to understand all the inner workings of Angular. We can just use the `<strong>input</strong>` function and we’re good to go 🚀.</p><h4>Why doesn’t Angular make all decorator inputs required by default?</h4><p>The reason is that Angular is used in a lot of different projects. Making all inputs required by default will break a lot of projects. That’s why we need to opt-in for this feature.</p><h3>Deriving state from inputs</h3><h4>Input setter with a method call</h4><p>With class fields, what we did to derive the state was to use input setters and call a method that will derive the state from the inputs.</p><pre>// deriving state from inputs with input setter and calling a method<br>export class UserComponent {<br>  _user: User | undefined;<br>  _images: string[] = [];<br><br>  favoriteImages: string[] = [];<br><br>  @Input() set user(user: User) {<br>    this._user = user;<br>    this.updateFavoriteImages();<br>  }<br><br>  @Input() set images(images: string[]) {<br>    this._images = images;<br>    this.updateFavoriteImages();<br>  }<br><br>  private updateFavoriteImages() {<br>    if (this._user &amp;&amp; this._images) {<br>      this.favoriteImages = this._images.filter(x =&gt; this._user.favoriteImages.includes(x.name));<br>    }<br>  }<br>}</pre><h4>Input setter with BehaviorSubject</h4><p>The input setter has the issue of not having access to all input changes, that’s why we used it mostly with <strong>BehaviorSubjects</strong> and handled the racing conditions with <strong>rxjs</strong> operators.</p><pre>// deriving state from inputs with input setter and BehaviorSubject<br>export class UserComponent {<br>  user$ = new BehaviorSubject&lt;User | undefined&gt;(undefined);<br>  images$ = new BehaviorSubject&lt;string[]&gt;([]);<br><br>  favoriteImages$ = combineLatest([this.user$, this.images$]).pipe(<br>    map(([user, images]) =&gt; {<br>      if (user &amp;&amp; images) {<br>        return images.filter(x =&gt; user.favoriteImages.includes(x.name));<br>      }<br>      return [];<br>    })<br>  );<br><br>  @Input() set user(user: User) {<br>    this.user$.next(user);<br>  }<br><br>  @Input() set images(images: string[]) {<br>    this.images$.next(images);<br>  }<br>}</pre><h4>ngOnChanges</h4><p><strong>ngOnChanges</strong> on the other hand, is called for every input change and it has access to all the inputs.</p><pre>// deriving state from inputs with ngOnChanges<br><br>export class UserComponent implements OnChanges {<br>  @Input() user: User | undefined;<br>  @Input() images: string[] = [];<br><br>  favoriteImages: string[] = [];<br><br>  ngOnChanges(changes: SimpleChanges) {<br>    if (changes.user || changes.images) {<br>      this.updateFavoriteImages();<br>    }<br>  }<br><br>  private updateFavoriteImages() {<br>    if (this.user &amp;&amp; this.images) {<br>      this.favoriteImages = this.images.filter(x =&gt; this.user.favoriteImages.includes(x.name));<br>    }<br>  }<br>}</pre><p>These are some of the patterns that we used to derive state from inputs.</p><h4>Signals 🚦</h4><p>Then signals were introduced and we started to use them to derive state from inputs.</p><pre>// deriving state from inputs with signals<br><br>export class UserComponent {<br>  user = signal&lt;User | undefined&gt;(undefined);<br>  images = signal&lt;string[]&gt;([]);<br><br>  favoriteImages = computed(() =&gt; {<br>    const user = this.user();<br>    if (user &amp;&amp; this.images().length) {<br>      return this.images().filter(x =&gt; user.favoriteImages.includes(x.name));<br>    }<br>    return [];<br>  });<br><br>  @Input({ alias: &#39;user&#39; }) set _user(user: User) {<br>    this.user.set(user);<br>  }<br><br>  @Input({ alias: &#39;images&#39; }) set _images(images: string[]) {<br>    this.images.set(images);<br>  }<br>}</pre><p>We just refactored the code to use <strong>signals</strong> instead of <strong>BehaviorSubjects</strong>. And <strong>computed</strong> instead of <strong>combineLatest</strong>.</p><h3>Signal Inputs</h3><p>Now, with signal inputs, we can just use the `input` function and we’re good to go 🚀.</p><pre>// deriving state from inputs with signal inputs<br><br>export class UserComponent {<br>  user = input.required&lt;User&gt;(); // Let&#39;s make the user input required for this example<br>  images = input&lt;string[]&gt;([]);<br><br>  favoriteImages = computed(() =&gt; {<br>    const user = this.user();<br>    if (user &amp;&amp; this.images().length) {<br>      return this.images().filter(x =&gt; user.favoriteImages.includes(x.name));<br>    }<br>    return [];<br>  });<br>}</pre><h4>Inputs + API calls</h4><p>This was easy to do with <strong>BehaviorSubjects</strong> because we can just <strong>pipe</strong> the <strong>observables</strong> and handle the racing conditions with rxjs operators.</p><pre>// inputs + api calls with BehaviorSubjects<br>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user$ = new BehaviorSubject&lt;User | undefined&gt;(undefined);<br><br>  favoriteImages$ = this.user$.pipe(<br>    switchMap(user =&gt; {<br>      if (user) {<br>        return this.imagesService.getImages(user.favoriteImages);<br>      }<br>      return of([]);<br>    })<br>  );<br><br>  @Input() set user(user: User) {<br>    this.user$.next(user);<br>  }<br>}</pre><p>With `<strong>ngOnChanges</strong>` we can do the same thing, but we need to handle the racing conditions ourselves.</p><pre>// inputs + api calls with ngOnChanges<br>export class UserComponent implements OnChanges, OnDestroy {<br>  private imagesService = inject(ImagesService);<br>  @Input() user: User | undefined;<br><br>  favoriteImages: string[] = [];<br><br>  private currentSub?: Subscription;<br><br>  ngOnChanges(changes: SimpleChanges) {<br>    if (changes.user) {<br>      this.updateFavoriteImages();<br>    }<br>  }<br><br>  private updateFavoriteImages() {<br>    if (this.user) {<br>      this.currentSub?.unsubscribe();<br><br>      this.currentSub = this.imagesService<br>        .getImages(this.user.favoriteImages)<br>        .subscribe(images =&gt; (this.favoriteImages = images));<br>    }<br>  }<br><br>  ngOnDestroy() {<br>    // unsubscribe from the observable when the component is destroyed<br>    this.currentSub?.unsubscribe(); <br>  }<br>}</pre><p>That’s too much code for something that should be simple. Also, if the API call depends on more than one input, we need to handle the racing conditions ourselves ⚠️.</p><h4>Signal Inputs + API calls</h4><p>To listen to input changes, we use the `<strong>effect</strong>` function.</p><p>In v17, `<strong>effect</strong>` is scheduled to run after all the inputs are initialized. So, it means even if we have an <strong>effect</strong> on the constructor, we can be sure that all the inputs are initialized (inside of it).</p><pre>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user = input.required&lt;User&gt;();<br><br>  constructor() {<br>    console.log(&#39;constructor - user&#39;, this.user()); // user is undefined here<br>    effect(() =&gt; {<br>      console.log(&#39;effect - user&#39;, this.user());<br>    });<br>  }<br><br>  ngOnInit() {<br>    console.log(&#39;init - user&#39;, this.user()); // user is defined here<br>  }<br>}</pre><pre>&lt;app-user [user]=&quot;user&quot; /&gt;</pre><p>This code will result in the following output:</p><pre>constructor - user undefined<br>init        - user { name: &#39;John&#39; };<br>effect      - user { name: &#39;John&#39; };</pre><p>Because of this, we can use the `<strong>effect</strong>` function to make API calls.</p><pre>// inputs + api calls with signal inputs<br><br>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user = input.required&lt;User&gt;();<br><br>  favoriteImages = signal&lt;string[]&gt;([]);<br><br>  constructor() {<br>    effect((onCleanup) =&gt; {<br>      const sub = this.imagesService.getImages(this.user().favoriteImages).subscribe(images =&gt; {<br>        this.favoriteImages.set(images);<br>      });<br>      onCleanup(() =&gt; sub.unsubscribe())<br>    });<br>  }<br>}</pre><p>This is great until we have to manage multiple input changes and derive state from them, while also maintaining the subscriptions .</p><h4>computedFrom (<a href="https://ngxtension.netlify.app/utilities/signals/computed-from/">ngxtension</a>) to the rescue 🛟</h4><p><strong>computedFrom</strong> was born out of the need to derive state from multiple sources (<em>observables</em>, <em>signals</em>, <em>signals from inputs</em>) and also to manage the subscriptions cleanly (without having to subscribe/unsubscribe manually ✅).</p><p>Read the whole story here:</p><p><a href="https://itnext.io/a-sweet-spot-between-signals-and-observables-a3c9620768f1">A sweet spot between signals and observables 🍬</a></p><p>This is how we can use it to derive state from inputs and API calls:</p><pre>// inputs + api calls with signal inputs + computedFrom<br><br>export class UserComponent {<br>  private imagesService = inject(ImagesService);<br>  user = input.required&lt;User&gt;();<br><br>  favoriteImages = computedFrom(<br>    [this.user], // sources<br>    switchMap(([user]) =&gt; this.imagesService.getImages(user.favoriteImages)), // side effect + computation<br>    { initialValue: [] } // options<br>  );<br>}</pre><p>If you have more sources, you can just add them to the array:</p><pre>favoriteImages = computedFrom(<br>  [this.user, this.imageOptions, /* ... more sources here */ ]<br>  switchMap(([user, options]) =&gt; <br>    this.imagesService.getImages(user.favoriteImages, options)<br>  ),<br>  { initialValue: [] } <br>);</pre><h3>Enea Jahollari 🅰 on Twitter: &quot;Using ngxtension utils to power apps 🚀? Look at this snippet doing an API call powered by signals on the outside and observables (HTTP call) on the inside.- injectQueryParams, injectParams -&gt; router signals- computedFrom -&gt; combineLatest with signalsRead more on the docs... pic.twitter.com/yfbrm8DPgw / Twitter&quot;</h3><p>Using ngxtension utils to power apps 🚀? Look at this snippet doing an API call powered by signals on the outside and observables (HTTP call) on the inside.- injectQueryParams, injectParams -&gt; router signals- computedFrom -&gt; combineLatest with signalsRead more on the docs... pic.twitter.com/yfbrm8DPgw</p><h3>Migrating to Signal Inputs</h3><p>You can go over all your inputs and start refactoring every input and its references one by one, or you can use some migration schematics that handle most of the basic usage patterns for you.</p><p>The <a href="https://ngxtension.netlify.app/"><strong>ngxtension</strong></a> library publishes some schematics you can use in an Angular or Nx workspace.</p><p>To use it you just have to run these two commands:</p><pre>npm install ngxtension<br>ng g ngxtension:convert-signal-inputs</pre><p>Find more about it in the docs: <a href="https://ngxtension.netlify.app/utilities/migrations/signal-inputs-migration/">Ngxtension Signal Inputs Migration</a> by <a href="https://twitter.com/Nartc1410">Chau Tran</a> 🪄</p><h3>To sum up</h3><p>With signal inputs, we can just use the `<strong>input</strong>` function and we’re good to go 🚀. We don’t have to fight with <strong>Typescript</strong> anymore or have to understand all the inner workings of Angular. We can just use the `<strong>input</strong>` function to derive state directly from inputs, to manage API calls more easily, and if we don’t want to maintain any glue code at all, <strong>computedFrom</strong> (ngxtension) is there to help us.</p><h4>The article was reviewed by:</h4><ul><li><a href="https://twitter.com/Jean__Meche"><strong>Matthieu Riegler</strong></a><strong> 🧑🏻‍💻 </strong>(Make sure to follow him on Twitter for everything Angular)</li></ul><h4>Other articles to read regarding signal inputs:</h4><ul><li><a href="https://dev.to/this-is-angular/diving-into-type-system-behind-angular-signal-inputs-2b88">Diving into Type System behind Angular Signal Inputs</a></li><li><a href="https://netbasal.com/revolutionizing-angular-introducing-the-new-signal-input-api-d0fc3c8777f2">Revolutionizing Angular: Introducing the New Signal Input API</a></li></ul><h3>Get better at Modern Angular ⚡️</h3><p>Master the latest features to build modern applications. Learn how to use standalone components, function guards &amp; interceptors, signals, the new inject method, and much more.</p><p>🔗 <a href="https://push-based.io/workshop/modern-angular">Modern Angular workshop from Push-Based.io</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*-N9RM2LSJDPihywl.png" /><figcaption>Modern Angular Workshop Agenda</figcaption></figure><h3>Thanks for reading!</h3><p>If this article was interesting and useful to you, and you want to learn more about Angular, support me by <a href="https://ko-fi.com/eneajahollari">buying me a coffee</a> ☕️ or follow me on X (formerly Twitter) <a href="https://twitter.com/Enea_Jahollari">@Enea_Jahollari</a> where I tweet and blog a lot about <strong>Angular</strong> latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more. 💎</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0ec967b301f" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/angular-signal-inputs-are-here-to-change-the-game-d0ec967b301f">Angular Signal Inputs are here to change the game 🎲</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A change detection, zone.js, zoneless, local change detection, and signals story ]]></title>
            <link>https://itnext.io/a-change-detection-zone-js-zoneless-local-change-detection-and-signals-story-9344079c3b9d?source=rss-eb2c15cb2c38------2</link>
            <guid isPermaLink="false">https://medium.com/p/9344079c3b9d</guid>
            <category><![CDATA[signal]]></category>
            <category><![CDATA[change-detection]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[zoneless]]></category>
            <category><![CDATA[performance]]></category>
            <dc:creator><![CDATA[Enea Jahollari]]></dc:creator>
            <pubDate>Thu, 21 Dec 2023 20:25:04 GMT</pubDate>
            <atom:updated>2024-01-04T11:47:26.442Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*N0FoEeuERFDvvkuOzhgOJA.png" /><figcaption>Photo by <a href="https://unsplash.com/@vork?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Mark Boss</a> on <a href="https://unsplash.com/photos/traffic-light-gHkKgHX0fbE?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>Angular is a component-driven framework. And just like every other framework out there, it is supposed to show the data to the user and refresh the view when the data changes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/667/1*eVpyKXodMU9thMSDn1XY4Q.png" /><figcaption>A UserCard component that shows user data in the template</figcaption></figure><p>Over time, we build more and more components and compose them together, and we may end up with a component tree like the one below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/814/1*QbEmmWPDvOTKw60oW-RKmw.png" /><figcaption>Component structure</figcaption></figure><p>But, how does Angular know when to refresh the view? How does it know when the data changes? How does it know when to run the change detection?</p><h4><strong>Change detection with synchronous code</strong></h4><p>Let’s start with a simple example. We have a component with a property <strong>name</strong> and a method <strong>changeName</strong>. When we click the button, we call the <strong>changeName</strong> method and change the <strong>name</strong> property.</p><pre>@Component({<br>  template: `<br>    &lt;button (click)=&quot;changeName()&quot;&gt;Change name&lt;/button&gt;<br>    &lt;p&gt;{{ name }}&lt;/p&gt;<br>  `<br>})<br>export class AppComponent {<br>  name = &#39;John&#39;;<br><br>  changeName() {<br>    this.name = &#39;Jane&#39;;<br>  }<br>}</pre><p>When we click the button, the <strong>changeName</strong> method is called, and because everything is wrapped by Angular, we can safely assume that after the name is changed, Angular can run some code to update the view (and everything will be in sync).</p><blockquote>⚠️ Imaginary under the hood Angular code:</blockquote><pre>component.changeName();<br>// This code is run  Angular will run change detection for the whole component tree because we may have updated some data in a service that is used by other components<br>angular.runChangeDetection(); </pre><p>This works fine! But, most of the time when we change the data, we don’t do it synchronously. We usually make an HTTP request, or have some timers, or wait for some other events to happen before updating the data. And that’s where the problems start.</p><h4><strong>Change detection with asynchronous code</strong></h4><p>Now, let’s say that we want to change the name after 1 second. We can do that with the <strong>setTimeout</strong> function.</p><pre>@Component({<br>  template: `<br>    &lt;button (click)=&quot;changeName()&quot;&gt;Change name&lt;/button&gt;<br>    &lt;p&gt;{{ name }}&lt;/p&gt;<br>  `<br>})<br>export class AppComponent {<br>  name = &#39;John&#39;;<br><br>  changeName() {<br>    setTimeout(() =&gt; {<br>      this.name = &#39;Jane&#39;;<br>    }, 1000);<br>  }<br>}</pre><p>When we click the button, the <strong>changeName</strong> method is called, and the <strong>setTimeout</strong> function is called. The <strong>setTimeout</strong> function will wait for 1 second and then call the callback function. The callback function will change the name to <strong>Jane</strong>.</p><p>And now, let’s add the same imaginary under-the-hood Angular code as before.</p><blockquote>⚠️ Imaginary under the hood Angular code:</blockquote><pre>component.changeName(); // uses setTimeout inside<br><br>// this code is run immediately after the changeName method is called<br>angular.runChangeDetection();</pre><p>Because of the <strong>call stack</strong>, the <strong>setTimeout</strong> callback will be called after the <strong>angular.runChangeDetection</strong> method. So, Angular ran the change detection but the name was not changed yet. And that’s why the view will not be updated. And that’s a broken application ⚠️. (In reality, it’s not, because we have 👇)</p><h3><strong>Zone.js to the rescue</strong></h3><p>Zone.js has been around since the early days of Angular 2.0. It is a library that monkey patches the browser APIs and enables us to hook into the lifecycle of the browser events. What does that mean? It means that we can run our code before and after the browser events.</p><pre>setTimeout(() =&gt; {<br>  console.log(&#39;Hello world&#39;);<br>}, 1000);</pre><p>The code above will print <strong>Hello world</strong> after 1 second. But, what if we want to run some code before or after the <strong>setTimeout</strong> callback?<em> You know, for business reasons </em>😄. A framework called <strong>Angular</strong> may want to run some code before and after the <strong>setTimeout</strong> callback.</p><p><strong>Zone.js</strong> enables us to do that. We can create a zone (Angular does create a zone too) and hook into the <strong>setTimeout</strong> callback.</p><pre>const zone = Zone.current.fork({<br>  onInvokeTask: (delegate, current, target, task, applyThis, applyArgs) =&gt; {<br>    console.log(&#39;Before setTimeout&#39;);<br>    delegate.invokeTask(target, task, applyThis, applyArgs);<br>    console.log(&#39;After setTimeout&#39;);<br>  }<br>});</pre><p>To run our <strong>setTimeout</strong> inside the zone, we need to use the <strong>zone.run()</strong> method.</p><pre>zone.run(() =&gt; {<br>  setTimeout(() =&gt; {<br>    console.log(&#39;Hello world&#39;);<br>  }, 1000);<br>});</pre><p>Now, when we run the code above, we will see the following output.</p><pre>Before setTimeout<br>Hello world<br>After setTimeout</pre><p>And that’s how zone.js works. It monkey patches the browser APIs and enables us to hook into the lifecycle of the browser events.</p><h3><strong>Zone.js + Angular</strong></h3><p>Angular loads <strong>zone.js</strong> by default in every application and creates a zone called <strong>NgZone</strong>. <strong>NgZone</strong> includes an <strong>Observable</strong> called <strong>onMicrotaskEmpty</strong>. This observable emits a value when there are no more microtasks in the queue. And that’s what Angular uses to know when all the asynchronous code is finished running and it can safely run the change detection.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/781/1*3Oe8-a_qFIOnAGEZsfM3vg.png" /><figcaption>NgZone wraps every angular application today</figcaption></figure><p>Let’s look at the underlying <a href="https://github.com/angular/angular/blob/c4de4e1f894001d8f80b70297c5e576f2d11ec6f/packages/core/src/change_detection/scheduling/ng_zone_scheduling.ts#L31">code</a>:</p><pre>// ng_zone_scheduling.ts NgZoneChangeDetectionScheduler<br>this._onMicrotaskEmptySubscription = this.zone.onMicrotaskEmpty.subscribe({<br>    next: () =&gt; this.zone.run(() =&gt; this.applicationRef.tick())<br>});</pre><p>What we see in the code above is that Angular will call the <a href="https://github.com/angular/angular/blob/c4de4e1f894001d8f80b70297c5e576f2d11ec6f/packages/core/src/application/application_ref.ts#L537"><strong>applicationRef.tick()</strong></a> method when the <strong>onMicrotaskEmpty</strong> observable emits a value. What’s this <strong>tick</strong> method 🤔? Do you remember the <strong>runChangeDetection</strong> method from the imaginary under-the-hood Angular code? Well, the <strong>tick</strong> method is the <strong>runChangeDetection</strong> method. It runs the change detection for the whole component tree <strong><em>synchronously</em></strong>.</p><p>But now, Angular knows that all the asynchronous code has finished running and it can <strong><em>safely</em></strong> run the change detection.</p><pre>tick(): void {<br>    // code removed for brevity<br>    for (let view of this._views) {<br>        // runs the change detection for a single component<br>        view.detectChanges(); <br>    }<br>}</pre><p>The <strong>tick</strong> method will iterate over all the root views (most of the time we have only one root view/component which is <strong>AppComponent</strong>) and run <strong>detectChanges</strong> synchronously.</p><h3><strong>Component Dirty marking</strong></h3><p>One other thing Angular does is that it marks the component as dirty when it knows something inside the component changed.</p><p>These are the things that mark the component as dirty:</p><ul><li>Events (click, mouseover, etc.)</li></ul><p>Every time we click a button with a listener in the template, Angular will wrap the callback function with a function called <a href="https://github.com/angular/angular/blob/c4de4e1f894001d8f80b70297c5e576f2d11ec6f/packages/core/src/render3/instructions/listener.ts#L260"><strong>wrapListenerIn_markDirtyAndPreventDefault</strong></a>. And as we can see from the name of the function 😅, it will mark the component as dirty.</p><pre>function wrapListener(): EventListener {<br>  return function wrapListenerIn_markDirtyAndPreventDefault(e: any) {<br>    // ... code removed for brevity<br>    markViewDirty(startView); // mark the component as dirty<br>  };<br>}</pre><ul><li>Changed inputs</li></ul><p>Also, while running the change detection, Angular will check if the input value of a component has changed (<strong>===</strong> check). If it has changed, it will mark the component as dirty. <a href="https://github.com/angular/angular/blob/c4de4e1f894001d8f80b70297c5e576f2d11ec6f/packages/core/src/render3/component_ref.ts#L348">Source code here</a>.</p><pre>setInput(name: string, value: unknown): void {<br>    // Do not set the input if it is the same as the last value<br>    if (Object.is(this.previousInputValues.get(name), value)) {<br>        return;<br>    }<br><br>    // code removed for brevity<br>    setInputsForProperty(lView[TVIEW], lView, dataValue, name, value);<br>    markViewDirty(childComponentLView); // mark the component as dirty<br>}</pre><ul><li>Output emissions</li></ul><p>To listen to output emissions in Angular we register an event in the template. As we saw before, the callback fn will be wrapped and when the event is emitted, the component will be marked as dirty.</p><p>Let’s see what this <a href="https://github.com/angular/angular/blob/c4de4e1f894001d8f80b70297c5e576f2d11ec6f/packages/core/src/render3/instructions/mark_view_dirty.ts#L24"><strong>markViewDirty</strong></a> function does.</p><pre>/**<br> * Marks current view and all ancestors dirty.<br> */<br>export function markViewDirty(lView: LView): LView|null {<br>  while (lView) {<br>    lView[FLAGS] |= LViewFlags.Dirty;<br>    const parent = getLViewParent(lView);<br>    // Stop traversing up as soon as you find a root view that wasn&#39;t attached to any container<br>    if (isRootView(lView) &amp;&amp; !parent) {<br>      return lView;<br>    }<br>    // continue otherwise<br>    lView = parent!;<br>  }<br>  return null;<br>}</pre><p>As we can read from the comment, the <strong>markViewDirty</strong> function will mark the current view and all ancestors dirty. Let’s see the image below to better understand what that means.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vWR8BluUbvyEdbezRbhYLw.png" /><figcaption>Dirty marking component and its ancestor up to the root</figcaption></figure><p>So, when we click the button, Angular will call our callback fn (<em>changeName</em>) and because it’s wrapped with the <strong>wrapListenerIn_markDirtyAndPreventDefault</strong> function, it will mark the component as dirty.</p><p>As we said before, Angular uses zone.js and wraps our app with it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qlIO2Wh0s9dSGhchJ9rh7g.png" /><figcaption>NgZone wraps Angular apps</figcaption></figure><p>After dirty marking to the top, <strong>wrapListenerIn_markDirtyAndPreventDefault </strong>fires and triggers zone.js</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DmRTN6SwNtGGqZA_E16Y_g.png" /><figcaption>Event listeners notify zone.js</figcaption></figure><p>Because Angular is listening to the <strong>onMicrotaskEmpty</strong> observable, and because the <strong>(click)</strong> registers an event listener, which zone has wrapped, zone will know that the event listener has finished running and it can emit a value to the <strong>onMicrotaskEmpty</strong> observable.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I6ceCK5GilF6J65lvyqoAw.png" /><figcaption><strong>onMicrotaskEmpty</strong> fires when there’s no microtask running anymore</figcaption></figure><p><strong>onMicrotaskEmpty </strong>tells Angular it’s time to run the change detection.</p><h3><strong>Component binding refresh</strong></h3><p>The moment Angular runs the change detection it will check every component from top to bottom. It will go over all the components (<strong>dirty</strong> and <strong>non-dirty</strong>) and check their bindings. If the binding has changed, it will update the view.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x08OitRwQ2qT7gIs3DF9bA.png" /></figure><p>But, why does Angular check all the components 🤔? Why doesn’t it check only the dirty components 🤔?</p><p>Well, because of the change detection strategy.</p><h3><strong>OnPush Change Detection</strong></h3><p>Angular has a change detection strategy called <strong>OnPush</strong>. When we use this strategy, Angular will only run the change detection for a component that is marked as dirty.</p><p>First, let’s change the change detection strategy to <strong>OnPush</strong>.</p><pre>@Component({<br>  // ...<br>  changeDetection: ChangeDetectionStrategy.OnPush<br>})<br>export class UserCard {}</pre><p>Let’s look at the graphic below to better understand how the change detection works with the <strong>OnPush</strong> strategy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zELCaBs7IW92PvceLa_IOA.png" /><figcaption>Some components now are marked as <strong>OnPush (and their children are implicitly OnPush components)</strong></figcaption></figure><p>Let’s do the same thing as before. Click a button in the component and change the name.</p><p>First, we will have the <strong>Dirty Marking phase</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AeeeFm-_fHGjbFAACMr1hA.png" /></figure><p>Then, the event listener will notify zone.js.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iP28hqjA-YdazbKm-zg_tA.png" /><figcaption>Event notifies zone.js</figcaption></figure><p>When everything async has finished running, <strong>onMicrotaskEmpty</strong> will fire.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*frosM42uC9BbaC8P3fIS5g.png" /></figure><p>Now, Angular will run the <strong>tick</strong> method, and what it will do is traverse all components from top to bottom and check each component.</p><p>If the component is:</p><ul><li><strong>OnPush</strong> + <strong>Non-Dirty</strong> -&gt; <strong>Skip</strong></li><li><strong>OnPush</strong> + <strong>Dirty</strong> -&gt; <strong>Check bindings </strong>-&gt; <strong>Refresh bindings </strong>-&gt; <strong>Check children</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Clr0BonprSL5sPAE-5JRTw.png" /></figure><p>As we can see, by using <strong>OnPush </strong>we can skip parts of the tree that we know haven’t had any changes.</p><h3><strong>OnPush + Observables + async pipe</strong></h3><p>When we work with Angular, observables have been our number one tool to manage data and state changes. To support observables, Angular provides the <strong>async</strong> pipe. The <strong>async</strong> pipe subscribes to an observable and returns the latest value. To let Angular know that the value has changed, it will call the <strong>markForCheck</strong> method that comes from the <strong>ChangeDetectorRef</strong> class (the component’s <strong>ChangeDetectorRef</strong>).</p><pre>@Pipe()<br>export class AsyncPipe implements OnDestroy, PipeTransform {<br>  constructor(ref: ChangeDetectorRef) {}<br><br>  transform&lt;T&gt;(obj: Observable&lt;T&gt;): T|null {<br>    // code removed for brevity<br>  }<br><br>  private _updateLatestValue(async: any, value: Object): void {<br>    // code removed for brevity<br>    this._ref!.markForCheck(); // &lt;-- marks component for check<br>  }<br>}</pre><p>I’ve written more about it here (create async pipe from scratch and understand how it works):</p><p><a href="https://itnext.io/async-pipe-is-not-pure-948f7b24e2d1">Async pipe is not pure 🤯</a></p><p>And what the <strong>markForCheck</strong> method does is that it will just call the <strong>markViewDirty</strong> function that we saw before.</p><pre>// view_ref.ts<br>markForCheck(): void {<br>  markViewDirty(this._cdRefInjectingView || this._lView);<br>}</pre><p>So, the same as before, if we use observables with <strong>async</strong> pipe in the template it will act the same as if we used the <strong>(click)</strong> event. It will mark the component as dirty and Angular will run the change detection.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LRpedou2RqKPanLTPRUbTQ.png" /><figcaption>data$ | async pipe marks component as dirty</figcaption></figure><h3>OnPush + Observables + Who is triggering zone.js?</h3><p>If our data changes without our interaction (click, mouseover etc.) probably there is a <strong>setTimeout</strong> or <strong>setInterval</strong> or an HTTP call being made somewhere under the hood that triggers zone.js.</p><p>Here’s how we can easily break it 🧨</p><pre>@Component({<br>  selector: &#39;todos&#39;,<br>  standalone: true,<br>  imports: [AsyncPipe, JsonPipe],<br>  template: `{{ todos$ | async | json }}`,<br>  changeDetection: ChangeDetectionStrategy.OnPush,<br>})<br>export class TodosComponent {<br>  private http = inject(HttpClient);<br>  private ngZone = inject(NgZone);<br><br>  todos$ = of([] as any[]);<br><br>  ngOnInit() {<br>    this.ngZone.runOutsideAngular(() =&gt; {<br>      setTimeout(() =&gt; {<br>        // this will be updated, but there&#39;s nothing triggering zonejs<br>        this.todos$ = this.getTodos();<br>      });<br>    });<br>  }<br><br>  getTodos() {<br>    return this.http<br>      .get&lt;any&gt;(&#39;https://jsonplaceholder.typicode.com/todos/1&#39;)<br>      .pipe(shareReplay(1));<br>  }<br>}</pre><p>What we have done here is:</p><ul><li>In <strong>ngOnInit,</strong> we have used <strong>ngZone.runOutsideAngular() </strong>an API that allows us to run things outside the Angular zone.</li><li>We use <strong>setTimeout</strong> (to skip the first task being run and also because Angular runs change detection at least once by default) and inside the <strong>setTimeout</strong>, we assign a value to the observable (yay we have a change).</li><li>Because <strong>setTimeout</strong> won’t run inside the zone, also the API call will be made outside the zone because the code is run inside <strong>runOutsideAngular, </strong>there is nothing notifying zonejs that something changed.</li><li>Run this code in your app and see that only “<strong>[]”</strong> will be shown in the browser.</li><li><strong>Broken State 🧨!</strong></li></ul><p>Not great 😄! But, one other thing that we start questioning is:</p><h4><strong>Why do we need to mark all the ancestors dirty?</strong></h4><p>The reason for this is simple, if we don’t mark all ancestors as dirty, we can get a broken state even faster. How?</p><p>Let’s see the above example again, but now, mark only the component and its children as dirty.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WR3R89nCi2ej-J0JDBUKjg.png" /></figure><p>So, we mark only the component that had the click and its children to be marked for check. The moment the <strong>tick</strong> happens it will get to the parent component which is <strong>OnPush, </strong>check that it’s not dirty, and skip it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eTO0ASGOnxsQm9sW-i6EVQ.png" /><figcaption>Broken state if we don’t mark ancestors as dirty when using markForCheck</figcaption></figure><p>That’s how we get to a broken state again 🧨!</p><h4><strong>Why can’t we just run the change detection for the component that is marked as dirty?</strong></h4><p>We can do that using the <strong>detectChanges</strong> method in the <strong>ChangeDetectorRef</strong> class. But it has its drawbacks. Because that method runs change detection synchronously, it can cause performance issues. Because everything will be done in the same browser task, it may block the main thread and cause jank. Imagine detecting changes for a list of 100 items every 1 or 2 seconds. That’s a lot of work for the browser.</p><h4><strong>markForCheck vs detectChanges (coalesced run vs sync runs)</strong></h4><p>When we use markForCheck we just tell Angular that a component is dirty, and nothing else happens, so even if we call markForCheck 1000 times it’s not going to be an issue. But, when we use <strong>detectChanges</strong>, Angular will do actual work like checking bindings and updating the view if needed. And that’s why we should use <strong>markForCheck</strong> instead of <strong>detectChanges</strong>.</p><h4><strong>Can’t we schedule </strong>detectChanges<strong> in the next browser task?</strong></h4><p>We can, that’s what <a href="https://www.rx-angular.io/docs/template/api/push-pipe"><strong>push pipe</strong></a> or <a href="https://www.rx-angular.io/docs/template/api/rx-let-directive"><strong>rxLet</strong></a> directive from <a href="https://www.rx-angular.io/"><strong>rx-angular</strong></a><strong> </strong>does. It schedules the change detection in the next browser task. But, it’s not a good idea to do that for every component. Because, if we have a list of 100 items, and we schedule the change detection for every item, we will have 100 browser tasks. And that’s not good for performance either.</p><h3>Signals 🚦</h3><p>The frontend world is moving towards signals. Solid.js, Svelte, Vue, and Angular are creating their signal implementations. And that’s because signals are a better way to <strong>manage state</strong> and <strong>state changes</strong>.</p><p>Signals in Angular have brought a lot of <strong>DX</strong> benefits. We can easily create and derive state and also run side effects when the state changes using effects. We don’t have to subscribe to them, we don’t have to unsubscribe from them, and we don’t have to worry about memory leaks 🧯.</p><p>We can just call them and they will return their current value.</p><pre>const name = signal(&#39;John&#39;); // create a signal with initial value<br>const upperCaseName = computed(() =&gt; name().toUpperCase()); // create a computed signal<br><br>effect(() =&gt; {<br>  console.log(name() + &#39; &#39; + upperCaseName()); // run side effect when name or upperCaseName changes<br>});<br><br>name.set(&#39;Jane&#39;); // change the name<br><br>// Output:<br>// John JOHN<br>// Jane JANE</pre><p>We can also use signals in the template just like normal function calls.</p><pre>@Component({<br>  template: `<br>    &lt;button (click)=&quot;name.set(&#39;Jane&#39;)&quot;&gt;Change name&lt;/button&gt;<br>    &lt;p&gt;{{ name() }}&lt;/p&gt;<br>  `<br>})<br>export class AppComponent {<br>  name = signal(&#39;John&#39;);<br>}</pre><p>If you ask if calling a function in the template is a good idea, I would say that it’s a good idea if the function call is cheap, and calling a signal is cheap. It’s just a function call that returns a value (without computing anything).</p><p>I’ve also written about it here:</p><p><a href="https://itnext.io/its-ok-to-use-function-calls-in-angular-templates-ffdd12b0789e">It’s ok to use function calls in Angular templates!</a></p><h3>Signals and Change Detection</h3><p>In v17 Angular change detection got an upgrade 🚀!</p><p>Angular templates now understand signals as something more than function calls. Below is one of the PRs making this a reality.</p><p><a href="https://github.com/angular/angular/pull/49153">feat(core): Mark components for check if they read a signal by atscott · Pull Request #49153 · angular/angular</a></p><p>Before we used the <strong>async</strong> pipe, so it would call the <strong>markForCheck</strong> method, and with signals, we just have to normally call them. Angular now will register an <strong>effect</strong> (<em>consumer</em>) that will listen to this signal and mark the template for check every time the signal changes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JvVZ73v8E5zXRzyCOnt3Vg.png" /></figure><p>The first benefit is that we don’t need async pipe anymore 🎉.</p><p>The second PR that improves change detection is this one:</p><p><a href="https://github.com/angular/angular/pull/51537">fix(core): Ensure backwards-referenced transplanted views are refreshed by atscott · Pull Request #51537 · angular/angular</a></p><p>Which solved an issue not related to signals but to change detection itself (which I won’t explain in detail).</p><p>By using the mechanism introduced by it, we got the 3rd PR which added <strong>Glo-cal</strong> change detection (Global + Local change detection) (a term coined by my friend @<a href="https://twitter.com/Jean__Meche">Matthieu Riegler</a> )</p><p><a href="https://github.com/angular/angular/pull/52302">perf(core): Update LView consumer to only mark component for check by atscott · Pull Request #52302 · angular/angular</a></p><p>So let’s better understand glo-cal (local) change detection 👇</p><h3><strong>Local Change Detection (Targeted mode)</strong></h3><p>One of those PRs I linked above introduced two new flags in Angular.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/522/1*gvQx3FEpysqIW8RpfX91Pw.png" /><figcaption>Two new flags (RefreshView &amp; HAS_CHILD_VIEWS_TO_REFRESH)</figcaption></figure><p>How do they work?</p><p>When the template effect runs, Angular will run a function called <strong>markViewForRefresh </strong>which sets the current component flag to <strong>RefreshView </strong>and then calls <strong>markAncestorsForTraversal </strong>which will mark all the ancestors with <strong>HAS_CHILD_VIEWS_TO_REFRESH.</strong></p><pre>/**<br> * Adds the `RefreshView` flag from the lView and updates HAS_CHILD_VIEWS_TO_REFRESH flag of<br> * parents.<br> */<br>export function markViewForRefresh(lView: LView) {<br>  if (lView[FLAGS] &amp; LViewFlags.RefreshView) {<br>    return;<br>  }<br>  lView[FLAGS] |= LViewFlags.RefreshView;<br>  if (viewAttachedToChangeDetector(lView)) {<br>    markAncestorsForTraversal(lView);<br>  }<br>}</pre><p>And here’s how it looks in the graph (updated tree structure to showcase more edge cases)👇</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DRDqyuI6pLlELqlA48m5vw.png" /></figure><p>So, the component that has signal changes is marked with the orange color border and the parents now have the ⏬ icon to tell that they have child views to refresh.</p><blockquote>NOTE: We still depend on zone.js to trigger change detection.</blockquote><p>The moment zone.js kicks in (the same reasons as before) it will call <strong>appRef.tick() </strong>and then we will have top-down change detection with some differences and new rules!</p><h3>Targeted Mode Rules</h3><p>NgZone triggers change detection in <strong>GlobalMode </strong>(it will go top-down checking &amp; refreshing all components)</p><p>In <strong>GlobalMode </strong>we check <strong>CheckAlways </strong><em>(normal component without any change detection strategy set)</em><strong> </strong>and <strong>Dirty OnPush</strong> components</p><p><strong>What triggers TargetedMode?</strong></p><ul><li>When in <strong>GlobalMode</strong> we encounter a <strong>Non-Dirty OnPush</strong> component, we switch to <strong>TargetedMode!</strong></li></ul><p>In <strong>TargetedMode:</strong></p><ul><li>Only refresh a view if it has the <strong>RefreshView</strong> flag set</li><li><strong>DO NOT</strong> Refresh <strong>CheckAlways</strong> or regular <strong>Dirty</strong> flag views</li><li>If we reach a view with <strong>RefreshView</strong> flag, traverse children in <strong>GlobalMode</strong></li></ul><p>Let’s go one by one on components.</p><ol><li>Root component is a normal component (<strong>CheckAlways</strong>) so we just check &amp; refresh bindings if needed and we continue to its children.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MwEruHykzCIvzX901X4WOw.png" /></figure><p>2. All <strong>CheckAlways</strong> components will continue to work the same as before.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JbNnofQxP7dnAqRpjmro_Q.png" /><figcaption>All CheckAlways components are refreshed</figcaption></figure><p>3. OnPush will continue to work the same, so if it’s not marked as dirty it won’t be checked.</p><p>4. If we check the other component that is <strong>OnPush</strong> + <strong>HAS_CHILD_VIEWS_TO_REFRESH </strong>but not dirty we get our trigger for <strong>TargetedMode</strong> (check the rules above)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XmdIz4ykbWYzPGWeAYfMqg.png" /></figure><p>6. The component itself is not going to be refreshed, let’s go to the children</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OltY0HzHDhj1MDLYEMabuw.png" /><figcaption><strong>TargetedMode</strong> on <strong>CheckAlways</strong> component -&gt; Skip</figcaption></figure><p>7. Then we reach a <strong>RefreshView</strong> component and we are on <strong>TargetedMode</strong>, which means we refresh the bindings. We also convert to <strong>GlobalMode</strong> to make sure <strong>CheckAlways </strong>children components also get refreshed correctly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*67Qjlpzdqai93xdGgH8Img.png" /></figure><p>8. Now we are in <strong>GlobalMode</strong> and we have a <strong>CheckAlways</strong> component, so we just refresh normally)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uvzUYErJ3jjenEzC9h2itA.png" /></figure><p>That’s all about the new Targeted Change Detection.</p><p>If we look at the final tree, we can see that we skipped more components than before when we reach an OnPush component that is not dirty.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/701/1*IAhmVb58R8oaE-IrGid43A.png" /></figure><blockquote>Targeted Change Detection = OnPush without footguns 🔫</blockquote><p>You can play with all these change detection rules in this app by <a href="https://github.com/JeanMeche">Mathieu Riegler</a> 🔨</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eqLX13lrKYs_4tKk9uk-hQ@2x.png" /><figcaption>Understand Angular Change Detection</figcaption></figure><p><a href="https://jeanmeche.github.io/angular-change-detection/">Understand Angular Change Detection</a></p><h3><strong>Zoneless Angular — </strong>Let’s remove zone.js from Angular</h3><p>The moment we remove zone.js from Angular we are left with code that runs but doesn’t update anything in the view (The bootstrap time of zone.js and all the pressure it puts in the browser gets removed too! We also remove 15kb from the bundle size 😎). Because nothing is triggering <strong>appRef.tick()</strong>.</p><p>But, Angular has some APIs that tell it that something changed. Which ones?</p><ul><li>markForCheck (used by async pipe)</li><li>signal changes</li><li>event handlers that mark view dirty</li><li>setting inputs on components created dynamically with <strong>setInput()</strong></li></ul><p>Also, OnPush components already works with the idea that it needs to tell Angular that something changed.</p><p>So, instead of having zone.js schedule <strong>tick()</strong> we can have Angular schedule <strong>tick()</strong> when it knows something changed.</p><p><a href="https://github.com/angular/angular/pull/53499">refactor(core): Add scheduler abstraction and notify when necessary by atscott · Pull Request #53499 · angular/angular</a></p><p>In this PR (<strong>experimental</strong>) we can see that <strong>markViewDirty</strong> now will notify the <strong>changeDetectionScheduler</strong> that something changed.</p><pre>export function markViewDirty(lView: LView): LView|null {<br>  lView[ENVIRONMENT].changeDetectionScheduler?.notify();<br>  // ... code removed for brevity<br>}</pre><p>The scheduler is supposed to schedule tick(), as we can see in this other <strong>experimental</strong> implementation of a zoneless scheduler.</p><p><a href="https://github.com/angular/angular/pull/53579">Add zoneless scheduler to the ApplicationRef.isStable indicator by atscott · Pull Request #53579 · angular/angular</a></p><pre>@Injectable({providedIn: &#39;root&#39;})<br>class ChangeDetectionSchedulerImpl implements ChangeDetectionScheduler {<br>  private appRef = inject(ApplicationRef);<br>  private taskService = inject(PendingTasks);<br>  private pendingRenderTaskId: number|null = null;<br><br>  notify(): void {<br>    if (this.pendingRenderTaskId !== null) return;<br><br>    this.pendingRenderTaskId = this.taskService.add();<br>    setTimeout(() =&gt; {<br>      try {<br>        if (!this.appRef.destroyed) {<br>          this.appRef.tick();<br>        }<br>      } finally {<br>        const taskId = this.pendingRenderTaskId!;<br>        this.pendingRenderTaskId = null;<br>        this.taskService.remove(taskId);<br>      }<br>    });<br>  }<br>}</pre><p>This is experimental, but we can see that basically, it will coalesce all notify() calls and run them only once (in this code is only once per macroTask — setTimeout, but maybe we get it only once per microTask — Promise.resolve())</p><p><strong>What are we supposed to understand from this?</strong></p><p>Apps that are currently using the OnPush change detection strategy will work fine in a zoneless angular world.</p><h3><strong>Zoneless Angular !== Glo-cal (local) change detection</strong></h3><p>Zoneless Angular is not the same as local change detection. Zoneless Angular is just removing <strong>zone.js </strong>from Angular and using the APIs that Angular already has to schedule tick().</p><p><strong>Real Local change detection</strong> is a new feature that will allow us to run change detection for only a sub-tree of components (not the whole component tree) that currently use the OnPush change detection strategy.</p><h3><strong>Signals change detection (No OnPush, No Zone.js, Signals only)</strong></h3><p>One thing signal change detection will bring is native unidirectional data flow (two-way data binding without headaches).</p><p>Watch this video <strong>Rethinking Reactivity w/ Alex Rickabaugh | Angular Nation</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F_yMrnSa2cTI%3Fstart%3D243%26feature%3Doembed%26start%3D243&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D_yMrnSa2cTI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F_yMrnSa2cTI%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/6b6a34fc42b89c19235c89202c74f831/href">https://medium.com/media/6b6a34fc42b89c19235c89202c74f831/href</a></iframe><p>While glo-cal change detection with OnPush and zoneless are great, with only signal components, we probably can do even better.</p><p>What if we didn’t have to use <strong>OnPush</strong>? Or mark the parents with <strong>HAS_CHILD_VIEWS_TO_REFRESH</strong> and run change detection for the whole component tree? What if we could just run change detection for the views inside components that have changed?</p><p>Read more in the RFC:</p><p><a href="https://github.com/angular/angular/discussions/49682">[Complete] Sub-RFC 3: Signal-based Components · angular angular · Discussion #49682</a></p><h3><strong>Happy New Year 2024! 🎉 A signals year for Angular 🚦!</strong></h3><p>This year Angular brought us a lot of new features. And I’m sure that next year will be even better.</p><p>Make sure to check out the</p><ul><li><a href="https://angular.dev/roadmap">Angular roadmap for 2024</a> 🎉</li><li><a href="https://angularchristmascalendar.com/">Angular Christmas Calendar 2023</a></li></ul><h3>Alex Rickabaugh on Twitter: &quot;2024 for @Angular will be the Year of the Signal. / Twitter&quot;</h3><p>2024 for @Angular will be the Year of the Signal.</p><h4>Credits where it’s due:</h4><ul><li><a href="https://twitter.com/synalx">Alex Rickabaugh</a> for answering all my questions about Angular</li><li><a href="https://twitter.com/AScottAngular">Andrew Scott</a> for every PR he has created till now</li><li><a href="https://twitter.com/Nartc1410">Chau Tran</a> and <a href="https://twitter.com/Jean__Meche">Matthieu Riegler</a> for the discussions about Angular internals</li><li><a href="https://twitter.com/Michael_Hladky">Michael Hladky</a> <a href="https://twitter.com/hoebbelsB">Julian Jandl</a> <a href="https://twitter.com/kh_kirill">Kirill Karnaukhov</a> <a href="https://twitter.com/edbzn">Edouard Bozon</a> <a href="https://twitter.com/LayZeeDK">Lars Gyrup Brink Nielsen</a> (RxAngular team)</li><li>The whole Angular team for the wonderful job they have been doing!</li></ul><h4>Get better at Modern Angular ⚡️</h4><p>Master the latest features to build modern applications. Learn how to use standalone components, function guards &amp; interceptors, signals, the new inject method, and much more.</p><p>🔗 <a href="https://push-based.io/workshop/modern-angular?source=enea-full-change-detection">Modern Angular workshop from Push-Based.io</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DOmhfx3sEzAXtWrLaibVlg@2x.png" /><figcaption>Modern Angular Workshop Agenda</figcaption></figure><h3>Thanks for reading!</h3><p>I tweet and blog a lot about <strong>Angular</strong> (latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more). 💎</p><p>If this article was interesting and useful to you, and you want to learn more about Angular, give me a follow at <a href="https://twitter.com/Enea_Jahollari">@Enea_Jahollari</a> or <a href="https://eneajahollari.medium.com/">Medium</a>. 📖</p><p>I’d appreciate it if you would support me by <a href="https://ko-fi.com/eneajahollari">buying me a coffee</a> ☕️. Thank you in advance 🙌</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9344079c3b9d" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/a-change-detection-zone-js-zoneless-local-change-detection-and-signals-story-9344079c3b9d">A change detection, zone.js, zoneless, local change detection, and signals story 📚</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>