<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Playful Programming Angular</title>
    <description>The latest articles on DEV Community by Playful Programming Angular (playfulprogramming-angular).</description>
    <link>https://dev.to/playfulprogramming-angular</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F3316%2F612534f5-7bba-4bfe-8455-998219bc57cf.png</url>
      <title>DEV Community: Playful Programming Angular</title>
      <link>https://dev.to/playfulprogramming-angular</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/playfulprogramming-angular"/>
    <language>en</language>
    <item>
      <title>Ng-News 26/24: OpenAPI Generator, slide.ng and Angular Compiler Benchmarks</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Tue, 10 Nov 2026 13:08:09 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2624-openapi-generator-slideng-and-angular-compiler-benchmarks-dji</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2624-openapi-generator-slideng-and-angular-compiler-benchmarks-dji</guid>
      <description>&lt;p&gt;&lt;strong&gt;OpenAPI Generator&lt;/strong&gt; can now generate Angular &lt;code&gt;httpResource&lt;/code&gt; methods, and &lt;strong&gt;slide.ng&lt;/strong&gt; brings Markdown presentations to Angular. Also in this episode are the first benchmarks of Angular’s new compiler, TanStack Query, error boundaries, and ng-prism 22.7.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/evalV3kNoek" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  How Much Faster Is Angular’s New Compiler?
&lt;/h2&gt;

&lt;p&gt;We’ve already covered the rewrite of Angular’s compiler, which uses Rust and Oxc. Now we finally have some numbers.&lt;/p&gt;

&lt;p&gt;Cédric Exbrayat ran the new pipeline on three projects. His cold-build benchmarks were roughly two to three times faster. On the largest project, memory usage went from about 2.8 GB to 1.4 GB.&lt;/p&gt;

&lt;p&gt;The TypeScript team reported about a tenfold speedup with its Go rewrite. Type checking is only one part of an Angular build, though. The other steps also contribute to the total, so speeding up TypeScript won’t give you the same speedup across the whole pipeline.&lt;/p&gt;

&lt;p&gt;You can already try the new pipeline in Analog. Brandon Roberts added experimental support for it to Analog’s Vite plugin.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://blog.ninja-squad.com/2026/10/27/how-much-faster-is-the-new-angular-compiler" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.ninja-squad.com%2Fimages%2Fsocial-card.png" height="800" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://blog.ninja-squad.com/2026/10/27/how-much-faster-is-the-new-angular-compiler" rel="noopener noreferrer" class="c-link"&gt;
            How much faster is the new Angular compiler? - Ninja Squad
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Angular is building a new Rust-backed compiler. What does it change, and what can we really expect for build performance?
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.ninja-squad.com%2Ffavicon.svg" width="256" height="256"&gt;
          blog.ninja-squad.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/analogjs/analog/pull/2695" rel="noopener noreferrer"&gt;Experimental compiler support in Analog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/" rel="noopener noreferrer"&gt;TypeScript 7.0 announcement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  OpenAPI Generator Adds &lt;code&gt;httpResource&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;When the backend is written in another language, or when an app talks to multiple backends, we often have to keep track of endpoint URLs and request and response types. We can write that code by hand, or we can generate it from an OpenAPI specification.&lt;/p&gt;

&lt;p&gt;OpenAPI Generator’s Angular client has traditionally exposed Observable methods using Angular’s &lt;code&gt;HttpClient&lt;/code&gt;. With version 7.27.0, we finally have support for &lt;code&gt;httpResource&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;There were already community projects that could do this. Now the official OpenAPI Generator can do it as well.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/OpenAPITools/openapi-generator/releases/tag/v7.27.0" rel="noopener noreferrer"&gt;OpenAPI Generator 7.27.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/OpenAPITools/openapi-generator/blob/v7.27.0/docs/generators/typescript-angular.md" rel="noopener noreferrer"&gt;Angular generator options&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  slide.ng
&lt;/h2&gt;

&lt;p&gt;Slidev lets developers write presentations in Markdown. It comes with features like code highlighting, live coding, Mermaid diagrams, and a presenter mode. Slidev itself is built with Vue.&lt;/p&gt;

&lt;p&gt;Erkam Yaman built slide.ng, an Angular implementation inspired by Slidev. It uses Slidev’s Markdown format and generates an Angular component for each slide. That means you can use your own Angular components in a presentation, alongside features like live coding, Mermaid, zoom, and presenter mode.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://slide-ng.dev/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fslide-ng.dev%2Fog.png" height="400" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://slide-ng.dev/" rel="noopener noreferrer" class="c-link"&gt;
            slide.ng | Slides in markdown, built with Angular
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Presentations written in markdown, with real Angular template syntax inside. Documentation for slide.ng.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fslide-ng.dev%2Ffavicon.ico" width="48" height="48"&gt;
          slide-ng.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Other News
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TanStack Query&lt;/strong&gt; helps you manage server state, including fetching and caching data. It's available for Angular, and Armen Vardanyan shows how it works in an Angular app in his hands-on stream on Angular Space.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/iY-ki8byjFc" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Error boundaries&lt;/strong&gt; are a bit like try-catch for templates. Angular 22.2’s &lt;code&gt;@boundary&lt;/code&gt; block lets you display a fallback if part of the template fails to render. Igor Sedov explains it in one of his animated Angular videos.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/gL0JrhG2wug" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;ng-prism&lt;/strong&gt; is a component gallery built for Angular libraries. Version 22.7 adds API pages for services and pipes and gives components and directives the same API page format. Alexander Spies goes through the changes in his release write-up.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/alexanderspies/not-everything-in-an-angular-library-is-a-component-whats-new-in-ng-prism-227-25jf" class="crayons-story__hidden-navigation-link"&gt;Not everything in an Angular library is a component: what's new in ng-prism 22.7&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/alexanderspies" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3909446%2Fef572afd-6e7d-408c-944c-eff3abe3637d.png" alt="alexanderspies profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/alexanderspies" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Alex
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Alex
                
                
              
              &lt;div id="story-author-preview-content-4954228" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/alexanderspies" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3909446%2Fef572afd-6e7d-408c-944c-eff3abe3637d.png" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Alex&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/alexanderspies/not-everything-in-an-angular-library-is-a-component-whats-new-in-ng-prism-227-25jf" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 31&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/alexanderspies/not-everything-in-an-angular-library-is-a-component-whats-new-in-ng-prism-227-25jf" id="article-link-4954228"&gt;
          Not everything in an Angular library is a component: what's new in ng-prism 22.7
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/angular"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;angular&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/alexanderspies/not-everything-in-an-angular-library-is-a-component-whats-new-in-ng-prism-227-25jf#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            9 min read
          &lt;/small&gt;
          
          &lt;div class="only-sidebar-menu-item trusted-visible-block print-hidden align-center"&gt;
                
                    
                
          &lt;/div&gt;

        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;h2&gt;
  
  
  Upcoming Conferences
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://ng-poland.pl/attendee-kit" rel="noopener noreferrer"&gt;NG Poland&lt;/a&gt; · 17 November 2026 · Warsaw&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.angularday.it/" rel="noopener noreferrer"&gt;angularday&lt;/a&gt; · 20 November 2026 · Verona&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://angular-tlv.com/" rel="noopener noreferrer"&gt;Aingular TLV&lt;/a&gt; · 14 December 2026 · Tel Aviv&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ng-switzerland.ch/" rel="noopener noreferrer"&gt;NG Switzerland&lt;/a&gt; · 11–12 February 2027 · Lucerne area&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ngbaguette.angulardevs.fr/en/" rel="noopener noreferrer"&gt;NG Baguette&lt;/a&gt; · 28 May 2027 · Paris&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ng-News 26/23: Pangular Inspector and Angular Compilation at ViteConf</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Sat, 31 Oct 2026 13:06:45 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/pangular-inspector-and-angular-compilation-at-viteconf-ng-news-2623-36g1</link>
      <guid>https://dev.to/playfulprogramming-angular/pangular-inspector-and-angular-compilation-at-viteconf-ng-news-2623-36g1</guid>
      <description>&lt;p&gt;&lt;strong&gt;Pangular Inspector&lt;/strong&gt; brings source scans and live inspection to Angular devtools. &lt;strong&gt;Alex Rickabaugh’s ViteConf talk, “Angular Compilation Past &amp;amp; Future,”&lt;/strong&gt; covers Angular’s compiler history and its Rust/Oxc work. Also in brief: Julian Jandl’s production SSR recording.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/jbYJglkKyGo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Pangular Inspector
&lt;/h2&gt;

&lt;p&gt;Devframe is a framework for writing devtools, already used by several tools outside Angular. It was created by Anthony Fu, the creator of Vitest and Slidev, and a core team member of Vue.js, Vite, and Nuxt.&lt;/p&gt;

&lt;p&gt;Anthony announced Devframe in September 2026. &lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://devfra.me/posts/pluggable-extensible-playful-devtools" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevfra.me%2F_og%2Fd%2Fc_DocsSatori%2Ctitle_~UGx1Z2dhYmxlLCBFeHRlbnNpYmxlLCBhbmQgUGxheWZ1bCBEZXZUb29scw%2Cdescription_~SW50cm9kdWN0aW9uIHRvIERldmZyYW1lLCBhIGZyYW1ld29yayBmb3IgYnVpbGRpbmcgcGx1Z2dhYmxlLCBleHRlbnNpYmxlLCBhbmQgcGxheWZ1bCBEZXZUb29scy4%2Cheadline_Blog%2Cp_Ii9wb3N0cy9wbHVnZ2FibGUtZXh0ZW5zaWJsZS1wbGF5ZnVsLWRldnRvb2xzIg%2Cs_iZFcl1OP6x4P1_kG.png" height="400" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://devfra.me/posts/pluggable-extensible-playful-devtools" rel="noopener noreferrer" class="c-link"&gt;
            Pluggable, Extensible, and Playful DevTools | Devframe
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Introduction to Devframe, a framework for building pluggable, extensible, and playful DevTools.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevfra.me%2Flogo.svg" width="500" height="500"&gt;
          devfra.me
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Now, Angular has a new tool built on it: Pangular Inspector, maintained by Erkam Yaman and Santosh Yadav.&lt;/p&gt;

&lt;p&gt;Santosh has been around the Angular community for quite some time. He is a GitHub Star, Nx Champion, and Google Developer Expert.&lt;/p&gt;

&lt;p&gt;Erkam maintains the Turkish translation of the Angular documentation and has recently contributed extensively to Angular Native - which we covered last episode - including its integration with Analog’s file-based routing.&lt;/p&gt;

&lt;p&gt;Pangular aims to become the unified devtools for Angular. Built on Devframe, it can scan the source code of an Angular app and inspect its live state.&lt;/p&gt;

&lt;p&gt;It shows components, signals, NgRx stores, services, forms, and routes. Source scans tell you what is declared in your project; live inspection shows the instances and values in the running application.&lt;/p&gt;

&lt;p&gt;That information is available through its inspector panel and to your coding agent through MCP.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://pangular-inspector.dev/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpangular-inspector.dev%2Fog.png" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://pangular-inspector.dev/" rel="noopener noreferrer" class="c-link"&gt;
            Pangular Inspector | The unified Angular devtools
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Inspect Angular components, signals, dependency injection, routes, forms and stores. In the page, from the CLI, or through a coding agent over MCP.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpangular-inspector.dev%2Ffavicon.ico" width="48" height="48"&gt;
          pangular-inspector.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/ng-native/ng-native/pull/509" rel="noopener noreferrer"&gt;Erkam’s Analog integration for Angular Native&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Compilation Past &amp;amp; Future
&lt;/h2&gt;

&lt;p&gt;Alex Rickabaugh also spoke at the online ViteConf. His talk, “Angular Compilation Past &amp;amp; Future,” starts with Angular’s compilation history before moving into the current work involving Rust and Oxc, which we discussed last episode as well.&lt;/p&gt;

&lt;p&gt;Alex described splitting Angular’s compiler into two parts. The expensive analysis would move to a native implementation written in Rust, while code generation would remain in Node.js.&lt;/p&gt;

&lt;p&gt;The choice of Rust is closely tied to Oxc, VoidZero’s JavaScript toolchain. Alex points to its adoption across modern JavaScript tools, including Vite, as a reason to build on it for the long term.&lt;/p&gt;

&lt;p&gt;Compilation would still start with a tsconfig. The Oxc-based Angular analyzer would extract metadata and pass it to the Node.js code generator, which he calls the preprocessor. That would produce either TypeScript with runtime code or a different file containing code for type checking and the language service.&lt;/p&gt;

&lt;p&gt;The following link includes a timestamp that takes you straight to Alex’s talk.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/PfyIEgLzNYI?start=32558" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Production SSR with Julian Jandl
&lt;/h2&gt;

&lt;p&gt;And the recording of Julian Jandl’s talk on SSR is now available. He presents the work he and his colleagues did on a betting platform, the challenges they encountered, and their solutions using custom strategies for Incremental Static Regeneration, or ISR.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/-sbgS9KMIpQ" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Upcoming conferences
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ng-poland.pl/attendee-kit" rel="noopener noreferrer"&gt;NG Poland&lt;/a&gt; - 17 November 2026, Warsaw.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.angularday.it/" rel="noopener noreferrer"&gt;angularday&lt;/a&gt; - 20 November 2026, Verona.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://angular-tlv.com/" rel="noopener noreferrer"&gt;Aingular TLV&lt;/a&gt; - 7 December 2026, Tel Aviv.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ng-switzerland.ch/" rel="noopener noreferrer"&gt;NG Switzerland&lt;/a&gt; - 11-12 February 2027, Lucerne area.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ngbaguette.angulardevs.fr/en/" rel="noopener noreferrer"&gt;NG Baguette&lt;/a&gt; - 28 May 2027, Paris.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Angular Addicts #54: Angular 22.2, TypeScript 7, Agentic UI &amp; more</title>
      <dc:creator>Gergely Szerovay</dc:creator>
      <pubDate>Wed, 28 Oct 2026 09:08:11 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/angular-addicts-54-angular-222-typescript-7-agentic-ui-more-84o</link>
      <guid>https://dev.to/playfulprogramming-angular/angular-addicts-54-angular-222-typescript-7-agentic-ui-more-84o</guid>
      <description>&lt;h2&gt;
  
  
  👋Hey fellow Angular Addict
&lt;/h2&gt;

&lt;p&gt;This is the 54th issue of the Angular Addicts Newsletter, a monthly collection of carefully selected Angular resources that caught my attention. (Here are the &lt;a href="https://www.angularaddicts.com/p/angular-addicts-53-ngrx-22-webmcp-copilot-kit" rel="noopener noreferrer"&gt;53rd&lt;/a&gt;, &lt;a href="https://www.angularaddicts.com/p/angular-addicts-52-copilot-kit-mcp-apps" rel="noopener noreferrer"&gt;52nd&lt;/a&gt; and &lt;a href="https://www.angularaddicts.com/p/angular-addicts-51-a2ui-signal-debouncing" rel="noopener noreferrer"&gt;51st&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  📢 Release announcements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📢 &lt;a href="https://blog.ninja-squad.com/2026/09/23/what-is-new-angular-22.2" rel="noopener noreferrer"&gt;What's new in Angular 22.2?&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/exbrayatcedric/" rel="noopener noreferrer"&gt;Cédric Exbrayat&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💎Angular Gems of September, 2026
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://blog.angular.dev/an-update-on-angulars-typescript-7-powered-compiler-9619a35e2b0a" rel="noopener noreferrer"&gt;An update on Angular’s TypeScript 7-powered Compiler&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://x.com/synalx" rel="noopener noreferrer"&gt;Alex Rickabaugh&lt;/a&gt; &amp;amp; &lt;a href="https://x.com/marktechson" rel="noopener noreferrer"&gt;Mark Techson&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://www.angulararchitects.io/en/blog/using-jev-for-agentic-ui-just-a-trend-or-a-game-changer/" rel="noopener noreferrer"&gt;Using Jev for Agentic UI: Just a Trend or a Game Changer?&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/manfred-steyer-84645821/" rel="noopener noreferrer"&gt;Manfred Steyer&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://www.angularspace.com/polymorpheus-a-tiny-tool-you-didnt-know-you-needed/" rel="noopener noreferrer"&gt;Polymorpheus: a tiny tool you didn’t know you needed&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://x.com/Waterplea" rel="noopener noreferrer"&gt;Alex Inkin&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://christianlydemann.com/the-evolution-of-security-in-angular-apps/" rel="noopener noreferrer"&gt;The Evolution of Security in Angular Apps&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/christian-l%C3%BCdemann-075652104/" rel="noopener noreferrer"&gt;Christian Lüdemann&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://medium.com/@pkengineering/angular-is-winning-and-most-developers-havent-noticed-yet-827e04e71da0" rel="noopener noreferrer"&gt;Angular Is Winning — And Most Developers Haven’t Noticed Yet&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By PK The Angular Guy&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://santoshyadav.dev/blog/2026-09-02-deploy-angular-ssr-on-cloudflare/" rel="noopener noreferrer"&gt;How to Deploy Angular SSR on Cloudflare Workers&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/santoshyadavdev/" rel="noopener noreferrer"&gt;Santosh Yadav&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://dev.to/gde/build-real-time-client-side-tts-in-angular-using-firebase-ai-logic-and-gemini-37hc"&gt;Build Real-Time Client-Side TTS in Angular Using Firebase AI Logic and Gemini&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/connieleung107/" rel="noopener noreferrer"&gt;Connie Leung&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://angular.love/component-harness-writing-tests-that-survive-refactors" rel="noopener noreferrer"&gt;Component Harness: Writing Tests That Survive Refactors&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/mi%C5%82osz-rutkowski-38a52b225/" rel="noopener noreferrer"&gt;Milosz Rutkowski&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://soverius.ai/blog/inside-macroquest-agent-generated-ui-in-angular-on-a-local-12b-model" rel="noopener noreferrer"&gt;Inside MacroQuest: agent-generated UI in Angular, on a local 12B model&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/muratsari1/" rel="noopener noreferrer"&gt;Murat Sari&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  👨‍💻About the author
&lt;/h2&gt;

&lt;p&gt;My name is &lt;a href="https://www.linkedin.com/in/gergelyszerovay/" rel="noopener noreferrer"&gt;Gergely Szerovay&lt;/a&gt;, I worked as a data scientist and full-stack developer for many years, and I have been working as frontend tech lead, focusing on Angular based frontend development. As part of my role, I'm constantly following how Angular and the frontend development scene in general is evolving. To share my knowledge, I started the &lt;a href="https://angularaddicts.com/" rel="noopener noreferrer"&gt;Angular Addicts&lt;/a&gt; monthly newsletter and publication in 2022, so that I can send you the best resources I come across each month. Whether you are a seasoned Angular Addict or a beginner, I got you covered. Let me know if you would like to be included as a writer. Let’s learn Angular together! &lt;a href="https://www.angularaddicts.com/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; 🔥&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://www.angularaddicts.com/" rel="noopener noreferrer"&gt;Substack (Angular Addicts)&lt;/a&gt;, &lt;a href="https://aiboosted.dev" rel="noopener noreferrer"&gt;Substack (AIBoosted.dev)&lt;/a&gt;, &lt;a href="https://medium.com/@GergelySzerovay" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;, &lt;a href="https://dev.to/gergelyszerovay"&gt;Dev.to&lt;/a&gt;, &lt;a href="https://twitter.com/GergelySzerovay" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/gergelyszerovay/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to learn more about Angular, and how to build AI apps with AI, Typescript, React and Angular!&lt;/p&gt;

&lt;h2&gt;
  
  
  🕹️Previous issues
&lt;/h2&gt;

&lt;p&gt;If you missed the previous issues of the newsletter, you can read them &lt;a href="https://www.angularaddicts.com/t/angular-addicts-monthly" rel="noopener noreferrer"&gt;here&lt;/a&gt;, these are the latest 3 issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.angularaddicts.com/p/angular-addicts-53-ngrx-22-webmcp-copilot-kit" rel="noopener noreferrer"&gt;Angular Addicts #53: NgRx 22, WebMCP, CopilotKit &amp;amp; more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.angularaddicts.com/p/angular-addicts-52-copilot-kit-mcp-apps" rel="noopener noreferrer"&gt;Angular Addicts #52: Angular Addicts #52: Angular 22.1, CopilotKit, MCP Apps, Signal Form Validators &amp;amp; more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.angularaddicts.com/p/angular-addicts-51-a2ui-signal-debouncing" rel="noopener noreferrer"&gt;Angular Addicts #51: spartan/ui 1.0, A2UI, Signal Debouncing &amp;amp; more&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📨 Submit your Angular resource
&lt;/h2&gt;

&lt;p&gt;Have you found or written an interesting Angular-related article, tweet or other resource lately? Please let me know here in the comments or send me a DM on &lt;a href="https://twitter.com/gergelyszerovay" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;! I might feature it in the next Angular Addicts issue!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Ng-News 26/22: TypeScript 7.1, Angular Native and Polymorpheus</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Thu, 15 Oct 2026 08:22:23 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2622-typescript-71-angular-native-and-polymorpheus-4ej2</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2622-typescript-71-angular-native-and-polymorpheus-4ej2</guid>
      <description>&lt;p&gt;Angular’s compiler and TypeScript 7.1, plus Angular Native for mobile apps. Also: Polymorpheus for flexible UI components and upcoming Angular conferences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular’s Compiler and TypeScript 7.1
&lt;/h2&gt;

&lt;p&gt;Angular code is not directly compiled by TypeScript, but by an Angular compiler which sits on top of TypeScript.&lt;/p&gt;

&lt;p&gt;TypeScript 7 is the current version and the first version which has been ported to Go. It promises up to 10 times faster compilation. Such a big change to TypeScript therefore also has a huge impact on the Angular compiler.&lt;/p&gt;

&lt;p&gt;The Angular compiler uses TypeScript's programmatic API. It imports and uses it like a library. TypeScript 7.0, though, doesn't have a programmatic API, but it is compatible with TypeScript 6, which means we can continue using TypeScript 6's programmatic API. So far so good.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/2kujjeqqsg1sc5hizoen.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2kujjeqqsg1sc5hizoen.png" alt="Simplified Angular compiler using TypeScript as a library: source enters Angular, Angular calls the programmatic API for parsing and transformation, and emits transformed TypeScript." width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Angular imports TypeScript as a library and calls its programmatic API. Simplified version.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With TypeScript 7.1, a new programmatic API is expected to become available. Angular will need that one to run on 7.1.&lt;/p&gt;

&lt;p&gt;Here's the problem. Angular's compiler is written in TypeScript but it now has to access a compiler which is written in Go. This means we have a language boundary. The new interop API will fix that, but it comes without the TypeScript transformer API, which Angular uses to rewrite our code.&lt;/p&gt;

&lt;p&gt;That's why Angular will use another very popular tool, Oxc, which is written in Rust and already used by Vite and other widespread tools. Roughly summarized, Angular uses Oxc throughout its various steps to analyze our code and prepare compilation tasks. Angular has two major pipelines. One which prepares our code by transforming it to a final form, and another one where it runs the type-check on the templates. At both ends, we will benefit from the newly gained speed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/bvat0g4s4yeebslyftoq.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbvat0g4s4yeebslyftoq.png" alt="Simplified Angular compiler diagram: Oxc parses and transforms code; application TypeScript goes to a bundler, while template-checking TypeScript goes to TypeScript 7.1." width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Simplified version of the two compiler paths, adapted from the episode animation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At the time of this writing the PR has already been merged into main. So we might already get a version of it in the upcoming version 22.3 of Angular.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://blog.angular.dev/an-update-on-angulars-typescript-7-powered-compiler-9619a35e2b0a" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;blog.angular.dev&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/angular/angular/pull/71259" rel="noopener noreferrer"&gt;Angular compiler PR&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Native
&lt;/h2&gt;

&lt;p&gt;Developing native applications for mobile hasn't been the greatest joy for Angular developers. We have Ionic, but it uses a WebView as a middle layer to display web UI. NativeScript does render truly native UI for both Android and iOS. But we never had something like React Native with its production-proven Fabric renderer and an ecosystem like Expo, which supports the whole development lifecycle.&lt;/p&gt;

&lt;p&gt;On 29 September, this changed. Angular Native was released by Ashley Hunter and has gained some traction in terms of contributors. It is an independent community project and is currently in alpha.&lt;/p&gt;

&lt;p&gt;The great thing is that its native rendering isn't built from scratch but uses React Native under the hood. That is possible because React Native's Fabric rendering infrastructure can be driven without React. In a typical React Native app, React's reconciler determines the changes to the component tree and passes the rendering work to Fabric. Angular Native drives Fabric without React's component tree or reconciler.&lt;/p&gt;

&lt;p&gt;Ashley Hunter made use of that separation and replaced Angular's renderer, which targets the DOM, with a native renderer that uses React Native's Fabric. Switching the renderer to a non-DOM target is not new. Chau Tran applies the same approach in Angular Three.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/uhy0adwftqaib9uldqd3.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuhy0adwftqaib9uldqd3.png" alt="Side-by-side React Native and Angular Native stacks. React or Angular Native drives Fabric, which renders native iOS and Android UI." width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The framework layer changes; Fabric and the native UI layers remain. Simplified version.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For us, that means we build on a production-proven native renderer, which is well maintained, and on top we have Angular Native as a project that integrates Angular via its official renderer extension points. The integration itself, though, is still in alpha.&lt;/p&gt;

&lt;p&gt;Since it is native and not DOM - again, Ionic uses a WebView - we also cannot just use existing components or UI libraries that depend on the browser. For native UI, we have to use the native ones. Familiar tags like div and p do work, but they are mapped to native views and text. There is an exception, though: dom-component lets us embed existing Angular web components, but then that part runs in a WebView. The logic, though, can stay as long as it doesn't depend on browser APIs.&lt;/p&gt;

&lt;p&gt;Angular Native also went the extra mile and integrated Tailwind, the Angular router, hot reload, and a testing library. It supports the React Native build environment with the bundler Metro and Expo, which is somewhat like what Nx or Angular CLI is to Angular, but goes further with cloud builds, app-store submission, and updates. So Angular doesn't just run on top of React Native, it also unlocks access to its ecosystem of native modules and tooling. React components and hooks, though, don't just work in Angular.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://ng-native.com/" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;ng-native.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Polymorpheus
&lt;/h2&gt;

&lt;p&gt;If you're designing a UI library for generic use, you have to support different use cases, and that can become complicated. For example, an input might start as a simple string. But then a caller needs a function which receives the context for that particular use. Or your users want to display full HTML instead - or even a whole component. Think of a tooltip, for example, where you might have a simple title. Then you use that tooltip inside a loop and need access to the current element, or you want certain formatting.&lt;/p&gt;

&lt;p&gt;If you are the author of that tooltip, there's a lot of work that goes into that component to make it applicable to as many use cases as possible.&lt;/p&gt;

&lt;p&gt;Alex Inkin is a lead developer behind Taiga UI, and those kinds of challenges are his bread and butter, so to speak. Alex has published an article on Angular Space where he discusses his library Polymorpheus, which is optimized exactly for these challenges, is used in Taiga UI, and can also be used by us.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.angularspace.com/polymorpheus-a-tiny-tool-you-didnt-know-you-needed/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2F2026%2F09%2Farticle-header-1200x800--14-.png" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.angularspace.com/polymorpheus-a-tiny-tool-you-didnt-know-you-needed/" rel="noopener noreferrer" class="c-link"&gt;
            Polymorpheus: a tiny tool you didn’t know you needed
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Explore a little open-source library that supercharges dynamic content in Angular apps.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2Fsize%2Fw256h256%2F2024%2F01%2F08074be6-4592-4425-9361-d2193562c3c3-removebg.png" width="256" height="256"&gt;
          angularspace.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/taiga-family/polymorpheus" rel="noopener noreferrer"&gt;Official Polymorpheus repository&lt;/a&gt;&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://taiga-ui.dev/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftaiga-ui.dev%2Fassets%2Fimages%2Fcard.jpg" height="419" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://taiga-ui.dev/" rel="noopener noreferrer" class="c-link"&gt;
            Taiga UI
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A powerful set of open source components for Angular
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftaiga-ui.dev%2Fassets%2Ffavicon-32x32.png" width="32" height="32"&gt;
          taiga-ui.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Upcoming conferences
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ng-poland.pl/attendee-kit" rel="noopener noreferrer"&gt;NG Poland&lt;/a&gt; - 17 November 2026, Warsaw.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.angularday.it/" rel="noopener noreferrer"&gt;angularday&lt;/a&gt; - 20 November 2026, Verona.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://angular-tlv.com/" rel="noopener noreferrer"&gt;Aingular TLV&lt;/a&gt; - 7 December 2026, Tel Aviv.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ng-switzerland.ch/" rel="noopener noreferrer"&gt;NG Switzerland&lt;/a&gt; - 11-12 February 2027, Lucerne area.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ngbaguette.angulardevs.fr/en/" rel="noopener noreferrer"&gt;NG Baguette&lt;/a&gt; - 28 May 2027, Paris.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ng-News 26/21: Angular 22.2: Router Resources, Error Boundaries, and Private Template Members</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Sat, 03 Oct 2026 17:04:33 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/angular-222-router-resources-error-boundaries-and-private-template-members-h52</link>
      <guid>https://dev.to/playfulprogramming-angular/angular-222-router-resources-error-boundaries-and-private-template-members-h52</guid>
      <description>&lt;p&gt;Angular 22.2 introduces &lt;strong&gt;router resources&lt;/strong&gt; and &lt;strong&gt;error boundaries&lt;/strong&gt;, both in developer preview. We can also access TypeScript &lt;code&gt;private&lt;/code&gt; members from a component's template.&lt;/p&gt;

&lt;p&gt;The demo application used in this article is available at &lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/ng-news-episode-26-21-angular-22-2-umromrq7?file=src/app/app.routes.ts" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Router Resources
&lt;/h2&gt;

&lt;p&gt;Fetching data via the router is a feature which other frameworks have already had for many years. Angular already had resolvers, but it is nice that it now also supports this in the "Angular way", i.e. via the resource feature.&lt;/p&gt;

&lt;p&gt;Modern Angular uses resources to load data asynchronously from the backend. Since creating a &lt;code&gt;resource&lt;/code&gt; or using functions on top of it, like &lt;code&gt;rxResource&lt;/code&gt;, starts loading immediately, we usually create the resource in a component, or the component gets it indirectly via an Angular service.&lt;/p&gt;

&lt;p&gt;That also means that we need to provide the code to handle the state of a resource. For example, is it loading, has it been initialized, etc.?&lt;/p&gt;

&lt;p&gt;The following example shows the component &lt;code&gt;HolidaysPage&lt;/code&gt;, which gets the resource from a &lt;code&gt;HolidayService&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;holidays-page.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HolidayCard&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./holiday-card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HolidayService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./holiday.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-holidays&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;HolidayCard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;app-title /&amp;gt;
    @if (holidays.isLoading()) {
      &amp;lt;p&amp;gt;Loading holidays...&amp;lt;/p&amp;gt;
    } @else if (holidays.error()) {
      &amp;lt;p&amp;gt;Could not load the holidays.&amp;lt;/p&amp;gt;
    } @else if (holidays.hasValue()) {
      @for (holiday of holidays.value(); track holiday.id) {
        &amp;lt;app-holiday-card [holiday]="holiday" /&amp;gt;
      }
    }
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HolidaysPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;holidays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HolidayService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;createHolidaysResource&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;holiday.service.ts (resource factory)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;createHolidaysResource&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;holidays&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The full service is available in StackBlitz.&lt;/p&gt;

&lt;p&gt;Router resources are an elegant way to simplify that.&lt;/p&gt;

&lt;p&gt;We can define a resource at the router level, where it fetches the data when the user navigates to that route. By default, it also blocks route activation, meaning the router only renders the component once the resource has successfully fetched its data. The component gets the fetched data via input binding, as if the data had been there all the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;holidays-routes.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HolidayService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./holiday.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HolidaysPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./holidays-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;holidays&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HolidaysPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;holidayService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HolidayService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;holidays&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;holidayService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHolidaysResource&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;holidays-page.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Holiday&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./holiday&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HolidayCard&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./holiday-card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-holidays&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;HolidayCard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;app-title /&amp;gt;
    @for (holiday of holidays(); track holiday.id) {
      &amp;lt;app-holiday-card [holiday]="holiday" /&amp;gt;
    }
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HolidaysPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;holidays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Holiday&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;holidays&lt;/code&gt; input matches the resource name in the route configuration. We also need to enable router resources and component input binding:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;app.config.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provideRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;withComponentInputBinding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;withRouterResources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./holidays-routes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;provideRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;withRouterResources&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;withComponentInputBinding&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If multiple resources are defined across nested routes or for one specific route, their data loads in parallel, which also improves the loading time for the end user.&lt;/p&gt;

&lt;p&gt;Router resources also have further options. They can, for example, be non-blocking, be created asynchronously, and much more. For more details, head to the &lt;a href="https://angular.dev/guide/routing/data-fetching-with-resources" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Error Boundaries
&lt;/h2&gt;

&lt;p&gt;Whenever an unhandled error is thrown during rendering or change detection, it can bubble up through the component hierarchy and interrupt rendering.&lt;/p&gt;

&lt;p&gt;For obvious reasons, we can catch errors in TypeScript with &lt;code&gt;try/catch&lt;/code&gt; so that we can isolate them.&lt;/p&gt;

&lt;p&gt;For demonstration, our &lt;code&gt;Title&lt;/code&gt; component throws an unhandled error. When it is used as a child component, it also causes problems for its parent view. In our case, the holiday cards would not be rendered, and &lt;code&gt;HolidaysPage&lt;/code&gt; stays empty.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;h1&amp;gt;Holidays&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The title could not be created&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;holidays-page.ts (template)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;app-title&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

@for (holiday of holidays(); track holiday.id) {
  &lt;span class="nt"&gt;&amp;lt;app-holiday-card&lt;/span&gt; &lt;span class="na"&gt;[holiday]=&lt;/span&gt;&lt;span class="s"&gt;"holiday"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Error boundaries bring the concept of a &lt;code&gt;try/catch&lt;/code&gt; block from TypeScript to the template.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;@boundary&lt;/code&gt; template block wraps the risky template and isolates the error within it. &lt;code&gt;Title&lt;/code&gt; will therefore cause no further havoc in the rest of the application.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;catch&lt;/code&gt; part would be &lt;code&gt;@error&lt;/code&gt;, where we can provide a fallback template:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;holidays-page.ts (template)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@boundary {
  &lt;span class="nt"&gt;&amp;lt;app-title&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
} @error {
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Holidays&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
}

@for (holiday of holidays(); track holiday.id) {
  &lt;span class="nt"&gt;&amp;lt;app-holiday-card&lt;/span&gt; &lt;span class="na"&gt;[holiday]=&lt;/span&gt;&lt;span class="s"&gt;"holiday"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There are more options, including access to the error, resetting a boundary, and selecting a fallback conditionally. For this example, a static fallback is enough. In the companion demo, use &lt;strong&gt;Broken title&lt;/strong&gt; to see that fallback while the holiday cards stay visible.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://angular.dev/guide/templates/error-boundaries" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fangular.dev%2Fassets%2Fimages%2Fng-image.jpg" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://angular.dev/guide/templates/error-boundaries" rel="noopener noreferrer" class="c-link"&gt;
            Error boundaries with @boundary • Angular
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            The web development framework for building modern apps.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fangular.dev%2Fassets%2Ficons%2Ffavicon-48x48.png" width="48" height="48"&gt;
          angular.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Private Members in Templates
&lt;/h2&gt;

&lt;p&gt;The third feature is a small change to the component class. We can now access TypeScript &lt;code&gt;private&lt;/code&gt; members from its template:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-private-title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;h1&amp;gt;{{ title() }}&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PrivateTitle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Holidays&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before Angular 22.2, we would normally make a component member (property or method) used by the template &lt;code&gt;public&lt;/code&gt; or &lt;code&gt;protected&lt;/code&gt;. &lt;code&gt;protected&lt;/code&gt; was the choice when the member was meant for the template rather than the component's public API, although subclasses could still access it.&lt;/p&gt;

&lt;p&gt;Now &lt;code&gt;private&lt;/code&gt; is also an option, and for members used only by the component and its template, it is the one I would recommend. From a conceptual perspective, the component's template and TypeScript class form one unit. Accessing a private member in the template underlines that perspective.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/issues/70514#issuecomment-5508086108" rel="noopener noreferrer"&gt;Angular team discussion: the component and its template form one unit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One distinction is important here. TypeScript's &lt;code&gt;private&lt;/code&gt; modifier and ECMAScript &lt;code&gt;#&lt;/code&gt; fields are different. A field that is private at runtime, like &lt;code&gt;#title&lt;/code&gt;, cannot be accessed directly by the template. It still makes sense for state that should stay inside the class.&lt;/p&gt;

&lt;p&gt;For the sake of consistency, future Angular code should therefore use TypeScript's &lt;code&gt;private&lt;/code&gt; for members that the template needs to access.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;protected&lt;/code&gt;, on the other hand, will likely disappear from template-only use or be used mainly for class inheritance.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Angular Addicts #53: NgRx 22, WebMCP, CopilotKit &amp; more</title>
      <dc:creator>Gergely Szerovay</dc:creator>
      <pubDate>Tue, 29 Sep 2026 07:19:56 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/angular-addicts-53-ngrx-22-webmcp-copilotkit-more-1l1f</link>
      <guid>https://dev.to/playfulprogramming-angular/angular-addicts-53-ngrx-22-webmcp-copilotkit-more-1l1f</guid>
      <description>&lt;h2&gt;
  
  
  👋Hey fellow Angular Addict
&lt;/h2&gt;

&lt;p&gt;This is the 53rd issue of the Angular Addicts Newsletter, a monthly collection of carefully selected Angular resources that caught my attention. (Here are the &lt;a href="https://www.angularaddicts.com/p/angular-addicts-52-copilot-kit-mcp-apps" rel="noopener noreferrer"&gt;52nd&lt;/a&gt;, &lt;a href="https://www.angularaddicts.com/p/angular-addicts-51-a2ui-signal-debouncing" rel="noopener noreferrer"&gt;51st&lt;/a&gt; and &lt;a href="https://www.angularaddicts.com/p/angular-addicts-50-angular-22-agentic-deploying" rel="noopener noreferrer"&gt;50th&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  📢 Release announcements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📢 &lt;a href="https://dev.to/ngrx/announcing-ngrx-v22-resource-extensions-dynamic-deep-signals-a-light-theme-and-more-5gci"&gt;Announcing NgRx v22: Resource Extensions, Dynamic Deep Signals, a Light Theme, and more!&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/markostanimirovic/" rel="noopener noreferrer"&gt;Marko Stanimirović&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💎Angular Gems of August, 2026
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://angularexperts.ch/blog/angular-signal-forms-custom-controls" rel="noopener noreferrer"&gt;Angular Signal Forms: Custom Controls Without ControlValueAccessor&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/kevin-kreuzer-a63b39121/" rel="noopener noreferrer"&gt;Kevin Kreuzer&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://www.copilotkit.ai/blog/copilotkit-for-angular" rel="noopener noreferrer"&gt;Introducing CopilotKit for Angular&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/rainerhahnekamp/" rel="noopener noreferrer"&gt;Rainer Hahnekamp&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/muratsari1/" rel="noopener noreferrer"&gt;Murat Sari&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://www.angulararchitects.io/en/blog/loop-engineering-with-super-mario-and-twelve-ai-coding-agents/" rel="noopener noreferrer"&gt;Loop Engineering with Super Mario and Twelve AI Coding Agents&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/manfred-steyer-84645821/" rel="noopener noreferrer"&gt;Manfred Steyer&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://www.angularspace.com/how-to-handle-global-errors-in-modern-zoneless-angular/" rel="noopener noreferrer"&gt;How to Handle Global Errors in Modern Zoneless Angular&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/jaroslaw-zolnowski/" rel="noopener noreferrer"&gt;Jaroslaw Zolnowski&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://dev.to/gdg/angular-webmcp-your-app-is-now-an-ai-tool-3bp4"&gt;Angular WebMCP — Your App is Now an AI Tool&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/giorgiogalassi/" rel="noopener noreferrer"&gt;Giorgio Galassi&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://angular.love/signal-forms-in-angular-21-complete-guide" rel="noopener noreferrer"&gt;Signal Forms in Angular 21 - Complete Guide&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/m-stefanczyk/" rel="noopener noreferrer"&gt;Mateusz Stefańczyk&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  👨‍💻About the author
&lt;/h2&gt;

&lt;p&gt;My name is &lt;a href="https://www.linkedin.com/in/gergelyszerovay/" rel="noopener noreferrer"&gt;Gergely Szerovay&lt;/a&gt;, I worked as a data scientist and full-stack developer for many years, and I have been working as frontend tech lead, focusing on Angular based frontend development. As part of my role, I'm constantly following how Angular and the frontend development scene in general is evolving. To share my knowledge, I started the &lt;a href="https://angularaddicts.com/" rel="noopener noreferrer"&gt;Angular Addicts&lt;/a&gt; monthly newsletter and publication in 2022, so that I can send you the best resources I come across each month. Whether you are a seasoned Angular Addict or a beginner, I got you covered. Let me know if you would like to be included as a writer. Let’s learn Angular together! &lt;a href="https://www.angularaddicts.com/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; 🔥&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://www.angularaddicts.com/" rel="noopener noreferrer"&gt;Substack (Angular Addicts)&lt;/a&gt;, &lt;a href="https://aiboosted.dev" rel="noopener noreferrer"&gt;Substack (AIBoosted.dev)&lt;/a&gt;, &lt;a href="https://medium.com/@GergelySzerovay" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;, &lt;a href="https://dev.to/gergelyszerovay"&gt;Dev.to&lt;/a&gt;, &lt;a href="https://twitter.com/GergelySzerovay" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/gergelyszerovay/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to learn more about Angular, and how to build AI apps with AI, Typescript, React and Angular!&lt;/p&gt;

&lt;h2&gt;
  
  
  🕹️Previous issues
&lt;/h2&gt;

&lt;p&gt;If you missed the previous issues of the newsletter, you can read them &lt;a href="https://www.angularaddicts.com/t/angular-addicts-monthly" rel="noopener noreferrer"&gt;here&lt;/a&gt;, these are the latest 3 issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.angularaddicts.com/p/angular-addicts-52-copilot-kit-mcp-apps" rel="noopener noreferrer"&gt;Angular Addicts #52: Angular Addicts #52: Angular 22.1, CopilotKit, MCP Apps, Signal Form Validators &amp;amp; more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.angularaddicts.com/p/angular-addicts-51-a2ui-signal-debouncing" rel="noopener noreferrer"&gt;Angular Addicts #51: spartan/ui 1.0, A2UI, Signal Debouncing &amp;amp; more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.angularaddicts.com/p/angular-addicts-50-angular-22-agentic-deploying" rel="noopener noreferrer"&gt;Angular Addicts #50: Angular 22, Agentic Angular, Deploying to the Cloud &amp;amp; more&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📨 Submit your Angular resource
&lt;/h2&gt;

&lt;p&gt;Have you found or written an interesting Angular-related article, tweet or other resource lately? Please let me know here in the comments or send me a DM on &lt;a href="https://twitter.com/gergelyszerovay" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;! I might feature it in the next Angular Addicts issue!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Route Resources in Angular: what the Router actually does with your Signal under the hood</title>
      <dc:creator>Nicolas Frizzarin</dc:creator>
      <pubDate>Tue, 15 Sep 2026 06:24:17 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/route-resources-in-angular-what-the-router-actually-does-with-your-signal-under-the-hood-2lc6</link>
      <guid>https://dev.to/playfulprogramming-angular/route-resources-in-angular-what-the-router-actually-does-with-your-signal-under-the-hood-2lc6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Route resolvers have been around in Angular for years, and they do their job, but they come with a price you pay on every navigation: they run one after the other, parent to child, and they can't be refreshed without triggering a full navigation. Angular now ships an alternative built directly on Signals, exposed through the router as a &lt;code&gt;resources&lt;/code&gt; route property. The official guide covers the "how to use it" part pretty well: &lt;a href="https://next.angular.dev/guide/routing/data-fetching-with-resources" rel="noopener noreferrer"&gt;https://next.angular.dev/guide/routing/data-fetching-with-resources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What the guide doesn't show you is what happens between the moment you write &lt;code&gt;resource({...})&lt;/code&gt; in your route config and the moment your component receives a value. There's an entire file dedicated to that, &lt;code&gt;router_resource.ts&lt;/code&gt;.&lt;br&gt;
This article is what I found in there (it's a depth technical article ): how blocking works, why your UI doesn't flash a loading skeleton when you navigate between two similar pages, and where a navigation cancellation can leave you stuck if you don't understand the reload guard.&lt;/p&gt;

&lt;p&gt;I'll assume you already know what a &lt;code&gt;resource()&lt;/code&gt; is (a &lt;code&gt;value()&lt;/code&gt;, an &lt;code&gt;isLoading()&lt;/code&gt;, an &lt;code&gt;error()&lt;/code&gt;, a &lt;code&gt;status()&lt;/code&gt;, and a &lt;code&gt;reload()&lt;/code&gt;, all as signals). If not, go read the &lt;a href="https://next.angular.dev/guide/signals/resource" rel="noopener noreferrer"&gt;Resource API guide&lt;/a&gt; first, this article builds on top of it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Turning it on
&lt;/h2&gt;

&lt;p&gt;Route resources are gated behind a feature you have to opt into, &lt;code&gt;withRouterResources()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;bootstrapApplication&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/platform-browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provideRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;withComponentInputBinding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;withRouterResources&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.routes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;bootstrapApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;provideRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;withComponentInputBinding&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;withRouterResources&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice &lt;code&gt;withComponentInputBinding()&lt;/code&gt; next to it. It's not mandatory to make resources work, but without it you'll have to reach into &lt;code&gt;ActivatedRoute.resources&lt;/code&gt; manually instead of getting your data as a plain component &lt;code&gt;input()&lt;/code&gt;. In practice you'll almost always want both together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining resources on a route
&lt;/h2&gt;

&lt;p&gt;A route now accepts a &lt;code&gt;resources&lt;/code&gt; property, a function returning a map of &lt;code&gt;Resource&lt;/code&gt; instances:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./product.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products/:sku&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProductService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;params&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sku&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sku&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;productService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBySku&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ctx&lt;/code&gt; here is a &lt;code&gt;ResourceContext&lt;/code&gt;, giving you &lt;code&gt;params&lt;/code&gt;, &lt;code&gt;queryParams&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, and a static &lt;code&gt;snapshot&lt;/code&gt;, all as signals. The &lt;code&gt;resources&lt;/code&gt; function itself runs in an injection context, which is why &lt;code&gt;inject(ProductService)&lt;/code&gt; works directly at the top, without a factory wrapper.&lt;/p&gt;

&lt;p&gt;One detail that will bite you if you skip it: pass the primitive you actually need to &lt;code&gt;params&lt;/code&gt;, not the whole object. &lt;code&gt;params: () =&amp;gt; ctx.params()&lt;/code&gt; looks harmless, but the router creates a fresh &lt;code&gt;params&lt;/code&gt; object on every navigation, so the resource sees a new reference every time and reloads even when &lt;code&gt;sku&lt;/code&gt; didn't change. &lt;code&gt;params: () =&amp;gt; ctx.params()['sku']&lt;/code&gt; fixes that, because now the resource only reacts to the primitive value.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;resources&lt;/code&gt; can also be &lt;code&gt;async&lt;/code&gt;, if you need a dynamic import before wiring things up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetchProductBySku&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./product-api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;params&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sku&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sku&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetchProductBySku&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any &lt;code&gt;Resource&lt;/code&gt; implementation is accepted, not just &lt;code&gt;resource()&lt;/code&gt;. If your team is still RxJS-heavy, &lt;code&gt;rxResource()&lt;/code&gt; works the same way, swapping &lt;code&gt;loader&lt;/code&gt; for &lt;code&gt;stream&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nl"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rxResource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;params&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sku&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sku&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;productService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getBySku&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Blocking vs non-blocking, and what actually gets bound to your input
&lt;/h2&gt;

&lt;p&gt;By default every resource is blocking: the router waits for it before activating the route. That has a nice consequence for your component, the input type is the resolved value &lt;code&gt;T&lt;/code&gt;, not &lt;code&gt;Resource&amp;lt;T&amp;gt;&lt;/code&gt;, because your component never sees a loading or error state, the router already handled that for you.&lt;/p&gt;

&lt;p&gt;If you don't want to block navigation, wrap the resource with &lt;code&gt;nonBlocking()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products/:sku&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;nonBlocking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;params&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sku&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sku&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;productService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBySku&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;params&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sku&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sku&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;reviewsService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getForProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;product&lt;/code&gt; won't block navigation, &lt;code&gt;reviews&lt;/code&gt; will. Your component now has to handle both shapes at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    @if (product().isLoading()) {
      &amp;lt;p&amp;gt;Loading product…&amp;lt;/p&amp;gt;
    } @else if (product().hasValue()) {
      &amp;lt;h1&amp;gt;{{ product().value().name }}&amp;lt;/h1&amp;gt;
    }
    &amp;lt;app-reviews [reviews]="reviews" /&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Resource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;reviews&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Review&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nonBlocking()&lt;/code&gt; itself is trivial, it just tags the resource with an internal symbol so the router knows to keep the wrapped &lt;code&gt;Resource&amp;lt;T&amp;gt;&lt;/code&gt; object as-is instead of unwrapping it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nonBlocking&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Resource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;InternalRouterResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="nx"&gt;BLOCKING_SYMBOL&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual unwrapping for blocking resources happens in &lt;code&gt;createResourceOutletBindingEffects&lt;/code&gt;, in the same file. It uses &lt;code&gt;reflectComponentType&lt;/code&gt; to read the component's declared inputs, then for every input name that matches a key in &lt;code&gt;route.resources&lt;/code&gt; and whose &lt;code&gt;BLOCKING_SYMBOL&lt;/code&gt; isn't explicitly &lt;code&gt;false&lt;/code&gt;, it sets up an &lt;code&gt;effect()&lt;/code&gt; that calls &lt;code&gt;componentRef.setInput(templateName, resource.value())&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;templateName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;mirror&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="nx"&gt;templateName&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;InternalRouterResource&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="nx"&gt;BLOCKING_SYMBOL&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;effectRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;componentRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templateName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;componentRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;createdEffects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;effectRef&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;handledKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templateName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things worth calling out here. First, the matching is done by input name against the resource map key, so &lt;code&gt;product: resource({...})&lt;/code&gt; only reaches an &lt;code&gt;@Input()&lt;/code&gt; (or &lt;code&gt;input()&lt;/code&gt;) literally named &lt;code&gt;product&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Rename one without the other and the binding silently stops working, there's no compile-time link between the two.&lt;/p&gt;

&lt;p&gt;Second, &lt;code&gt;handledKeys&lt;/code&gt; is returned to the caller so that the router's standard data-binding subscription (&lt;code&gt;RoutedComponentInputBinder&lt;/code&gt;) skips those keys. Non-blocking resources are never added to &lt;code&gt;handledKeys&lt;/code&gt;, they go through that standard data stream instead, bound as the full &lt;code&gt;Resource&lt;/code&gt; object.&lt;/p&gt;

&lt;h2&gt;
  
  
  What &lt;code&gt;routerResource()&lt;/code&gt; actually wraps
&lt;/h2&gt;

&lt;p&gt;Every resource you hand to the &lt;code&gt;resources&lt;/code&gt; map gets passed through &lt;code&gt;routerResource()&lt;/code&gt; internally before the router uses it. This is the function doing the heavy lifting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;routerResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Resource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Resource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Injector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snapshotSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;frozenSnapshot&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createTransactionalSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resourceFromSnapshots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshotSignal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;InternalRouterResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SOURCE_RESOURCE_SYMBOL&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;BLOCKING_SYMBOL&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;InternalRouterResource&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="nx"&gt;BLOCKING_SYMBOL&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...reload wiring omitted here, see below&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It doesn't touch your loader, your params function, or your original resource at all. It reads your resource's &lt;code&gt;snapshot()&lt;/code&gt; signal (a &lt;code&gt;ResourceSnapshot&lt;/code&gt;, the internal shape carrying status/value/error together) through &lt;code&gt;createTransactionalSnapshot&lt;/code&gt;, and rebuilds a brand-new &lt;code&gt;Resource&lt;/code&gt; from that snapshot stream using &lt;code&gt;resourceFromSnapshots&lt;/code&gt;. Your original resource is kept around under &lt;code&gt;SOURCE_RESOURCE_SYMBOL&lt;/code&gt;, purely so &lt;code&gt;reload()&lt;/code&gt; can delegate to it later. Everything the router hands to your component is this wrapper, not your original resource instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The frozen snapshot: why navigating doesn't flash a loading spinner
&lt;/h2&gt;

&lt;p&gt;This is the part I found genuinely clever. When you navigate from &lt;code&gt;/products/1&lt;/code&gt; to &lt;code&gt;/products/2&lt;/code&gt;, both routes resolve to the same component and the same &lt;code&gt;product&lt;/code&gt; resource key, just with a different &lt;code&gt;sku&lt;/code&gt; param. Naively, that resource would immediately flip to &lt;code&gt;isLoading()&lt;/code&gt; the moment the param changes, and your component would render a loading skeleton for a split second before the new product shows up. The router avoids that by freezing the resource's snapshot for the duration of the navigation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;createTransactionalSnapshot&lt;/code&gt; subscribes to &lt;code&gt;router.events&lt;/code&gt; and reacts to five event types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationStart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;isRollbackRecoveryPending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;frozenSnapshot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;frozenSnapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationEnd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;frozenSnapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;isRollbackRecoveryPending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationSkipped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;frozenSnapshot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;isRollbackRecoveryPending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationCancel&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isRollback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationError&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationCancel&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;NavigationCancellationCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SupersededByNewNavigation&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;NavigationCancellationCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Redirect&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isRollback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;isRollbackRecoveryPending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the exposed &lt;code&gt;snapshot&lt;/code&gt; signal is simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;frozenSnapshot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the flow for a plain, successful navigation is: &lt;code&gt;NavigationStart&lt;/code&gt; fires, the router grabs whatever the source resource's snapshot currently is (the old product, already resolved) and locks it in &lt;code&gt;frozenSnapshot&lt;/code&gt;. From that point on, even though the underlying resource has already started loading the new &lt;code&gt;sku&lt;/code&gt; behind the scenes, your component keeps rendering the frozen, old value — no &lt;code&gt;isLoading&lt;/code&gt; flicker, no jump to an empty state. When &lt;code&gt;NavigationEnd&lt;/code&gt; fires, the freeze is lifted, &lt;code&gt;frozenSnapshot&lt;/code&gt; goes back to &lt;code&gt;null&lt;/code&gt;, and the &lt;code&gt;computed&lt;/code&gt; falls through to &lt;code&gt;source.snapshot()&lt;/code&gt;, which by then holds the new product.&lt;/p&gt;

&lt;p&gt;There's a subtlety in that &lt;code&gt;if (frozenSnapshot() === null)&lt;/code&gt; guard on &lt;code&gt;NavigationStart&lt;/code&gt;. If a second navigation starts while the first hasn't finished (you click fast between two product cards), the router won't re-freeze on top of an existing freeze, it keeps the original snapshot from before the first navigation began. That's intentional, it prevents freezing an intermediate, already-stale value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rollback recovery: the part almost nobody thinks about
&lt;/h2&gt;

&lt;p&gt;Here's a scenario the guide only mentions briefly but the source code handles explicitly. Say a &lt;code&gt;canActivate&lt;/code&gt; guard rejects a navigation to &lt;code&gt;/products/2&lt;/code&gt;. The router cancels it and rolls the URL and route params back to &lt;code&gt;/products/1&lt;/code&gt;. That rollback is itself a change in the params signal your resource depends on, from &lt;code&gt;2&lt;/code&gt; back to &lt;code&gt;1&lt;/code&gt;, so your resource, doing exactly what it's supposed to, fires a new load for &lt;code&gt;sku: 1&lt;/code&gt; — data it already had, and had already shown a second ago.&lt;/p&gt;

&lt;p&gt;Without extra handling, that would mean: user clicks, sees the current product freeze for a moment (&lt;code&gt;NavigationStart&lt;/code&gt;), sees the guard reject it, then sees a loading flash for the product they were already looking at. The code guards against exactly that with &lt;code&gt;isRollbackRecoveryPending&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationCancel&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isRollback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationError&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NavigationCancel&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;NavigationCancellationCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SupersededByNewNavigation&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;NavigationCancellationCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Redirect&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isRollback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;isRollbackRecoveryPending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cancellations caused by a newer navigation superseding this one, or by an internal redirect, are not treated as a rollback (the frozen snapshot gets released normally through the navigation that superseded it). Everything else, guard rejections, &lt;code&gt;NavigationError&lt;/code&gt;, is treated as a rollback, and the frozen snapshot is kept alive until the resource has actually settled again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isRollbackRecoveryPending&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;isRollbackRecoveryPending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;frozenSnapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The freeze only lifts once &lt;code&gt;source.isLoading()&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt; again, which in the rollback case happens once the resource has re-fetched (or, if it's cached, re-resolved instantly) the old param value. From the user's perspective, nothing happened, the product they were looking at stayed exactly as it was, even though under the hood a full reload was silently triggered and absorbed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;reload()&lt;/code&gt; sometimes just returns &lt;code&gt;false&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Route resources expose &lt;code&gt;.reload()&lt;/code&gt;, but it's not a direct passthrough to your original resource's &lt;code&gt;.reload()&lt;/code&gt;. It's guarded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;frozenSnapshot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you call &lt;code&gt;.reload()&lt;/code&gt; while a navigation is pending, or while the router is in the middle of a rollback recovery, the call is rejected and returns &lt;code&gt;false&lt;/code&gt;, your original resource's &lt;code&gt;reload()&lt;/code&gt; is never invoked. The reasoning tracks with everything above: during those windows the router is already managing the resource's lifecycle for you, and a manual reload sneaking in would fight with that transition tracking, possibly unfreezing something the router is deliberately keeping frozen. If your source resource doesn't implement &lt;code&gt;reload&lt;/code&gt; at all (a custom &lt;code&gt;Resource&lt;/code&gt; that only has &lt;code&gt;loader&lt;/code&gt;, say), &lt;code&gt;res.reload&lt;/code&gt; is just &lt;code&gt;() =&amp;gt; false&lt;/code&gt; unconditionally.&lt;/p&gt;

&lt;p&gt;This is worth checking for in your own code. If you wire a refresh button to &lt;code&gt;userResource?.reload()&lt;/code&gt; and nothing happens, the boolean return value is telling you exactly why, it's just easy to ignore a boolean you don't check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;button (click)="refresh()"&amp;gt;Refresh&amp;lt;/button&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;productResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ActivatedRoute&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;product&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;didReload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productResource&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;didReload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Reload skipped, a navigation transition is in progress.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Redirecting from inside a loader
&lt;/h2&gt;

&lt;p&gt;Blocking resources can redirect before the route ever activates, by throwing a &lt;code&gt;RedirectCommand&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nl"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;params&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sku&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;abortSignal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;productService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBySku&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;abortSignal&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RedirectCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/not-found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;abortSignal&lt;/code&gt; in the loader arguments, forward it into your fetch call. When the router supersedes a navigation or rolls it back, it aborts the in-flight request through that signal instead of letting an orphaned request finish and update state nobody asked for anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this gets uncomfortable
&lt;/h2&gt;

&lt;p&gt;Everything above is solid engineering, but a few things are worth flagging before you rely on this in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's a developer preview API (22.2 at the time of writing).&lt;/strong&gt; The shapes of &lt;code&gt;ResourceContext&lt;/code&gt;, &lt;code&gt;nonBlocking&lt;/code&gt;, and the internal snapshot mechanism can change between minors. If you build a design system component library around &lt;code&gt;route.resources&lt;/code&gt;, expect to revisit it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blocking-resource errors kill the entire navigation, not just the affected component.&lt;/strong&gt; If you have three parallel blocking resources on a route and one of them throws, the router cancels the whole navigation and fires &lt;code&gt;NavigationError&lt;/code&gt;, even if the other two resolved fine and their data would have been perfectly usable. There's no equivalent of a partial activation, you either get every blocking resource or none of them. &lt;code&gt;nonBlocking()&lt;/code&gt; sidesteps this, but only if you're willing to accept the full &lt;code&gt;Resource&amp;lt;T&amp;gt;&lt;/code&gt; object as your input type instead of the unwrapped value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The input binding is name-matching, not type-checked.&lt;/strong&gt; &lt;code&gt;createResourceOutletBindingEffects&lt;/code&gt; matches on &lt;code&gt;templateName&lt;/code&gt; between your &lt;code&gt;resources&lt;/code&gt; map and your component's declared inputs. Rename an input, rename a resource key, or introduce an alias, and the binding breaks silently. TypeScript won't catch this for you, you'll find out at runtime when the input stays &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual reload has a silent failure mode.&lt;/strong&gt; As shown above, &lt;code&gt;.reload()&lt;/code&gt; returns &lt;code&gt;false&lt;/code&gt; during transitions and rollback recovery instead of throwing or queuing the request. That's the right call for correctness, but it means a "refresh" button clicked at the wrong moment does nothing, and your only way to notice is checking the boolean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Params identity is a footgun the type system won't warn you about.&lt;/strong&gt; Passing &lt;code&gt;ctx.params()&lt;/code&gt; instead of &lt;code&gt;ctx.params()['id']&lt;/code&gt; compiles fine and works fine in your first manual test, then quietly reloads on every navigation once you actually have more than one route parameter changing shape. This is exactly the kind of bug that survives a demo and shows up three sprints later as "why does this refetch on every click."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing route resources properly means testing through the router.&lt;/strong&gt; Because the freezing and rollback logic lives on &lt;code&gt;router.events&lt;/code&gt; subscriptions tied to &lt;code&gt;NavigationStart&lt;/code&gt; / &lt;code&gt;NavigationEnd&lt;/code&gt; / &lt;code&gt;NavigationCancel&lt;/code&gt;, a shallow component test that stubs your service won't exercise any of that behavior. You need a &lt;code&gt;RouterTestingHarness&lt;/code&gt; (or equivalent) actually driving navigations to see the freeze/unfreeze cycle at all, plain &lt;code&gt;TestBed.createComponent&lt;/code&gt; won't cut it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Route resources solve a real problem, resolvers force a sequential waterfall and can't be refreshed without a full renavigation. What the docs describe as "the router masks loading states during pending navigations" is, under the hood, a &lt;code&gt;computed&lt;/code&gt; signal falling back between a frozen snapshot and the live one, driven by five router events and one small state machine for rollback recovery. It's not magic, it's a resource wrapper subscribing to navigation lifecycle events and freezing a value at the right moment, then releasing it at the right moment.&lt;/p&gt;

&lt;p&gt;If you're adopting this feature now, keep it away from anything load-bearing until it graduates out of developer preview, and keep an eye on that &lt;code&gt;reload()&lt;/code&gt; return value.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>web</category>
    </item>
    <item>
      <title>Optimus UI, NG Switzerland, and NgRx 22</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Thu, 10 Sep 2026 20:05:14 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/optimus-ui-ng-switzerland-and-ngrx-22-32ag</link>
      <guid>https://dev.to/playfulprogramming-angular/optimus-ui-ng-switzerland-and-ngrx-22-32ag</guid>
      <description>&lt;p&gt;&lt;strong&gt;Optimus UI&lt;/strong&gt;, &lt;strong&gt;NG Switzerland&lt;/strong&gt;, and &lt;strong&gt;NgRx 22&lt;/strong&gt; headline this episode.&lt;/p&gt;

&lt;p&gt;Also in brief: new Angular Space podcast episodes and articles, Micro Frontends, Native Federation v4, RxJS 9, and two Angular community deep dives.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/u2WBf2F7tKI" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimus UI
&lt;/h2&gt;

&lt;p&gt;Let's start with Optimus UI. In episode 26-17, we explained that PrimeNG, one of the most popular UI libraries, would become more of a commercial product. Because of that, a fork was created called Optimus UI, which keeps the library fully open source without requiring any additional licence.&lt;/p&gt;

&lt;p&gt;Optimus UI was first published as version 1. Later, version 2 followed, aligning it with Angular 22.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://optimus.openng.org/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Foptimus.openng.org%2Fopen-graph-logo.png" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://optimus.openng.org/" rel="noopener noreferrer" class="c-link"&gt;
            Optimus UI - Angular UI Component Library
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Optimus UI is a community-maintained, MIT licensed suite of 80+ accessible Angular UI components.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Foptimus.openng.org%2Flogo-icon.svg" width="83" height="87"&gt;
          optimus.openng.org
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/openng-org/optimus-ui" rel="noopener noreferrer"&gt;Optimus UI on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  NG Switzerland
&lt;/h2&gt;

&lt;p&gt;Dominic Bachmann, who is one of the people behind OpenNG, which hosts Optimus UI but also other projects, has now started to organize a conference in Switzerland - in Lucerne to be precise.&lt;/p&gt;

&lt;p&gt;NG Switzerland will take place on February 11-12, 2027. The call for papers is already open and ticket sales have also started. So, for us, that makes it the first already confirmed conference for next year.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://ng-switzerland.ch/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fng-switzerland.ch%2Fog-default.png" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://ng-switzerland.ch/" rel="noopener noreferrer" class="c-link"&gt;
            NG Switzerland — 11–12 February 2027, Lucerne, Switzerland
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            The Angular conference in the heart of Switzerland. 11–12 February 2027, Lucerne, Switzerland.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fng-switzerland.ch%2Ffavicon.svg" width="32" height="32"&gt;
          ng-switzerland.ch
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Angular Space Podcast
&lt;/h2&gt;

&lt;p&gt;Armen Vardanyan also came back from his summer holidays with his Angular Space podcast. We already had three different episodes: one about machine learning, another one about RAG, and another episode about Agentic UI, where I was also a guest.&lt;/p&gt;

&lt;p&gt;So in the end, all three new episodes focus very much on AI topics around Angular.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/JI_IwQYnEyU" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Ht0g8mROV6M" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Scw5jAnVHo8" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Space Articles
&lt;/h2&gt;

&lt;p&gt;Angular Space is not just a podcast, but also a platform where different developers can publish their articles. Recently, we got four new articles by Jaroslaw Zolnowski, Paweł Ostromecki, and Emmanuel Oyibo.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.angularspace.com/how-to-handle-global-errors-in-modern-zoneless-angular/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2F2026%2F08%2Farticle-header-1200x800--9-.png" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.angularspace.com/how-to-handle-global-errors-in-modern-zoneless-angular/" rel="noopener noreferrer" class="c-link"&gt;
            How to Handle Global Errors in Modern Zoneless Angular
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2Fsize%2Fw256h256%2F2024%2F01%2F08074be6-4592-4425-9361-d2193562c3c3-removebg.png" width="256" height="256"&gt;
          angularspace.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.angularspace.com/want-to-speak-at-a-conferences-heres-what-ive-learned/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2F2026%2F09%2Farticle-header-1200x800--12-.png" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.angularspace.com/want-to-speak-at-a-conferences-heres-what-ive-learned/" rel="noopener noreferrer" class="c-link"&gt;
            Want to Speak at a Conferences? Here’s What I’ve Learned
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2Fsize%2Fw256h256%2F2024%2F01%2F08074be6-4592-4425-9361-d2193562c3c3-removebg.png" width="256" height="256"&gt;
          angularspace.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.angularspace.com/code-became-cheap-did-developer-knowledge-too/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2F2026%2F08%2Farticle-header-1200x800--10-.png" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.angularspace.com/code-became-cheap-did-developer-knowledge-too/" rel="noopener noreferrer" class="c-link"&gt;
            Code Became Cheap. Did Developer Knowledge Too?
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2Fsize%2Fw256h256%2F2024%2F01%2F08074be6-4592-4425-9361-d2193562c3c3-removebg.png" width="256" height="256"&gt;
          angularspace.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.angularspace.com/best-api-integration-platforms-for-saas-and-agents/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2F2026%2F08%2Farticle-header-1200x800--11-.jpg" height="533" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.angularspace.com/best-api-integration-platforms-for-saas-and-agents/" rel="noopener noreferrer" class="c-link"&gt;
            The best API integration platforms for SaaS apps and agents in 2026
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A hands-on guide for Angular and TypeScript teams.  compared six platforms and focused on how easily each fits into an Angular app and how much backend control you retain when an integration goes beyond the standard flow.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ghost.io%2Fc%2F3f%2F63%2F3f6333b8-1f83-4017-8426-91bfbc264d81%2Fcontent%2Fimages%2Fsize%2Fw256h256%2F2024%2F01%2F08074be6-4592-4425-9361-d2193562c3c3-removebg.png" width="256" height="256"&gt;
          angularspace.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Micro Frontends
&lt;/h2&gt;

&lt;p&gt;Stefan Haas, Senior Software Engineer at Microsoft, wrote quite a detailed article on Micro Frontends in general. He explains the difference between the Federation approaches - Native Federation and Module Federation - and iframes. He argues that large enterprise companies very often go with iframes, not because of performance - they are actually paying a performance price - but because of the isolation. That is really important when multiple applications have been developed for many years and don't work together so easily.&lt;/p&gt;

&lt;p&gt;Stefan also mentions that the Federation approaches can be combined with Web Components. But again, that doesn't give you the same level of isolation that you find with iframes.&lt;/p&gt;

&lt;p&gt;Stefan sees Native and Module Federation as a perfect fit, especially for greenfield projects, where you can define the boundaries and make sure that everything works together. And he also mentions another, newer alternative called Web Fragments.&lt;/p&gt;

&lt;p&gt;All in all, it is a very good and detailed guide to the Micro Frontends landscape and the pros and cons of the various approaches.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://stefanhaas.dev/article/how-big-tech-builds-micro-frontends/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstefanhaas.dev%2Fog%2Fhow-big-tech-builds-micro-frontends.png" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://stefanhaas.dev/article/how-big-tech-builds-micro-frontends/" rel="noopener noreferrer" class="c-link"&gt;
            How Big Tech Builds Micro Frontends
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Mention iframes to a frontend developer and watch their face. Then look at what Google Cloud Console, Spotify, Salesforce and SAP actually run inside their largest products.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstefanhaas.dev%2Ffavicon.svg" width="32" height="32"&gt;
          stefanhaas.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Native Federation v4
&lt;/h2&gt;

&lt;p&gt;Staying with Micro Frontends, Angular Meetup Graz also hosted a special online meetup with multiple talks around Native Federation version 4. So, if you are interested, you can check out those talks as well. The full recording is available on YouTube.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/bG_eZM02Vfw" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  NgRx 22
&lt;/h2&gt;

&lt;p&gt;NgRx 22 is finally out. The headline feature is new experimental support for resources called Resource Extensions.&lt;/p&gt;

&lt;p&gt;For example, you can apply an extension which makes the resource keep the previous value while a new value is loading after its reactive parameters change. You could also build that behavior yourself with &lt;code&gt;snapshot()&lt;/code&gt; and some additional state logic, but with Resource Extensions, you stay on the resource itself. This means you can still write to the value, and it doesn't lose the more specific type when you're using, for example, &lt;code&gt;httpResource&lt;/code&gt; or other resource types. So that is a little bit more than what you normally get with snapshots.&lt;/p&gt;

&lt;p&gt;Another tiny addition is &lt;code&gt;SignalStoreFeatureType&lt;/code&gt;. That is a utility type for custom features which makes reusing them easier.&lt;/p&gt;

&lt;p&gt;All of that and more is covered in the official NgRx blog post on dev.to.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ngrx/announcing-ngrx-v22-resource-extensions-dynamic-deep-signals-a-light-theme-and-more-5gci" class="crayons-story__hidden-navigation-link"&gt;Announcing NgRx v22: Resource Extensions, Dynamic Deep Signals, a Light Theme, and more!&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/ngrx"&gt;
            &lt;img alt="NgRx logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F5016%2Fa8dc55b2-63c3-4e96-917c-2c18727a650a.png" class="crayons-logo__image" width="800" height="846"&gt;
          &lt;/a&gt;

          &lt;a href="/markostanimirovic" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F455571%2F51bedc18-8017-4569-a25d-30a74074bcb9.jpg" alt="markostanimirovic profile" class="crayons-avatar__image" width="500" height="500"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/markostanimirovic" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Marko Stanimirović
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Marko Stanimirović
                
                
              
              &lt;div id="story-author-preview-content-4469856" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/markostanimirovic" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F455571%2F51bedc18-8017-4569-a25d-30a74074bcb9.jpg" class="crayons-avatar__image" alt="" width="500" height="500"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Marko Stanimirović&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/ngrx" class="crayons-story__secondary fw-medium"&gt;NgRx&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/ngrx/announcing-ngrx-v22-resource-extensions-dynamic-deep-signals-a-light-theme-and-more-5gci" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ngrx/announcing-ngrx-v22-resource-extensions-dynamic-deep-signals-a-light-theme-and-more-5gci" id="article-link-4469856"&gt;
          Announcing NgRx v22: Resource Extensions, Dynamic Deep Signals, a Light Theme, and more!
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ngrx"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ngrx&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/angular"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;angular&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ngrx/announcing-ngrx-v22-resource-extensions-dynamic-deep-signals-a-light-theme-and-more-5gci" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;13&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ngrx/announcing-ngrx-v22-resource-extensions-dynamic-deep-signals-a-light-theme-and-more-5gci#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;h2&gt;
  
  
  RxJS 9
&lt;/h2&gt;

&lt;p&gt;And after about two and a half years, work on the next generation of RxJS has resumed. There was never a stable version 8 of RxJS, although there were 15 alpha releases and more work was done on it. But now the work continues as RxJS version 9.&lt;/p&gt;

&lt;p&gt;The idea is that RxJS 9 builds on the native &lt;code&gt;Observable&lt;/code&gt; from the web platform. It is not yet broadly available in browsers. If the browser does not support it, RxJS installs a fallback.&lt;/p&gt;

&lt;p&gt;The first beta, &lt;code&gt;9.0.0-beta.0&lt;/code&gt;, was released on August 4, 2026, and announced on August 5.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ReactiveX/rxjs" rel="noopener noreferrer"&gt;RxJS on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ReactiveX/rxjs/releases/tag/9.0.0-beta.0" rel="noopener noreferrer"&gt;RxJS 9.0.0-beta.0 release&lt;/a&gt;&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://benlesh.com/posts/rxjs-9-built-on-the-web-platform/" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;benlesh.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Angular Articles
&lt;/h2&gt;

&lt;p&gt;And then we have two further articles. The first one is more like a comment by Andrés Gesteira on whether Angular is still opinionated. It is a very good read. He analyzes the changes that we have recently seen in the Angular style guide and presents his opinion on them. So, as I said, it is more like a comment article.&lt;/p&gt;

&lt;p&gt;The other one is a technical deep dive by Jaime Burgos. His article takes a deep dive into &lt;code&gt;@defer&lt;/code&gt;. This is not just about how a defer block works or about its edge cases. It is really about how it works internally and what the compiler generates. So, if you are interested in those things, definitely have a look at it.&lt;/p&gt;

&lt;p&gt;Jaime is a very active contributor to the Angular project, so he definitely knows quite a lot about what is going on.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://quantum-quirks.hashnode.dev/is-angular-still-opinionated" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fuploads%2Fcovers%2F656758a193baa1f51f2e0c22%2F54717ee2-10fa-4089-8a12-cd7b31841754.png" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://quantum-quirks.hashnode.dev/is-angular-still-opinionated" rel="noopener noreferrer" class="c-link"&gt;
            Is Angular Still Opinionated? The New Style Guide
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Angular’s new style guide dropped file suffixes, feature-folder rules, and CLI opinions. This article asks if the framework is still opinionated.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fquantum-quirks.hashnode.dev%2Ffavicon.ico" width="256" height="256"&gt;
          quantum-quirks.hashnode.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://medium.com/@jaimeburgostejada/inside-angulars-defer-the-instructions-behind-deferrable-views-7a40f90c5d0f" rel="noopener noreferrer"&gt;Inside Angular's @defer: The Instructions Behind Deferrable Views&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/pull/67190" rel="noopener noreferrer"&gt;Angular PR #67190&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/pull/66112" rel="noopener noreferrer"&gt;Angular PR #66112&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/pull/68333" rel="noopener noreferrer"&gt;Angular PR #68333&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/pull/70187" rel="noopener noreferrer"&gt;Angular PR #70187&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>programming</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Angular Addicts #52: Angular Addicts #52: Angular 22.1, CopilotKit, MCP Apps, Signal Form Validators &amp; more</title>
      <dc:creator>Gergely Szerovay</dc:creator>
      <pubDate>Thu, 27 Aug 2026 07:40:18 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/angular-addicts-52-angular-addicts-52-angular-221-copilotkit-mcp-apps-signal-form-3ml3</link>
      <guid>https://dev.to/playfulprogramming-angular/angular-addicts-52-angular-addicts-52-angular-221-copilotkit-mcp-apps-signal-form-3ml3</guid>
      <description>&lt;h2&gt;
  
  
  👋Hey fellow Angular Addict
&lt;/h2&gt;

&lt;p&gt;This is the 52nd issue of the Angular Addicts Newsletter, a monthly collection of carefully selected Angular resources that caught my attention. (Here are the &lt;a href="https://www.angularaddicts.com/p/angular-addicts-51-a2ui-signal-debouncing" rel="noopener noreferrer"&gt;51st&lt;/a&gt;, &lt;a href="https://www.angularaddicts.com/p/angular-addicts-50-angular-22-agentic-deploying" rel="noopener noreferrer"&gt;50th&lt;/a&gt; and &lt;a href="https://www.angularaddicts.com/p/angular-addicts-49-analogjs-25-agentic-angular" rel="noopener noreferrer"&gt;49th&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  📢 Release announcements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📢 &lt;a href="https://blog.ninja-squad.com/2026/07/29/what-is-new-angular-22.1" rel="noopener noreferrer"&gt;What's new in Angular 22.1?&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/exbrayatcedric/" rel="noopener noreferrer"&gt;Cédric Exbrayat&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📢 &lt;a href="https://dev.to/copilotkit/introducing-angular-support-for-copilotkit-bring-any-agent-into-your-app-2f3e"&gt;Introducing Angular support for CopilotKit: bring any Agent into your app&lt;/a&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  📢 &lt;a href="https://nx.dev/blog/nx-23-1-release" rel="noopener noreferrer"&gt;Nx 23.1 Is Here: Per-Run Performance Reports, TypeScript 6, and Angular 22 | Nx Blog&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/juristr/" rel="noopener noreferrer"&gt;Juri Strumpflohner&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💎Angular Gems of July, 2026
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://dev.to/brandontroberts/choosing-angular-in-the-age-of-agents-1bo7"&gt;Choosing Angular in the Age of Agents&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/brandontroberts/" rel="noopener noreferrer"&gt;Brandon Roberts&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://angular.love/one-validator-to-rule-them-all-part-2-advanced-error-handling-with-multi-language-support" rel="noopener noreferrer"&gt;One Validator to Rule Them All — Part 2: Advanced Error Handling with multi-language support&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/gabor-kotel/" rel="noopener noreferrer"&gt;Gábor Kötél&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://www.angulararchitects.io/en/blog/mcp-apps-in-angular-with-copilotkit-rich-chat-interfaces-instead-of-text-responses/" rel="noopener noreferrer"&gt;MCP Apps in Angular with CopilotKit: Rich Chat Interfaces Instead of Text Responses&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/manfred-steyer-84645821/" rel="noopener noreferrer"&gt;Manfred Steyer&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://push-based.io/article/faster-builds-slower-applications-optimizing-angulars-bundle-output" rel="noopener noreferrer"&gt;Faster Builds, Slower Applications? Optimizing Angular's Bundle Output&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/christopher-p-holder/" rel="noopener noreferrer"&gt;Christopher Holder&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;a href="https://blog.angulartraining.com/how-to-add-async-http-validators-to-angular-signal-forms-df020267c130" rel="noopener noreferrer"&gt;How to Add Async HTTP Validators to Angular Signal Forms&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By &lt;a href="https://www.linkedin.com/in/achautard/" rel="noopener noreferrer"&gt;Alain Chautard&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  👨‍💻About the author
&lt;/h2&gt;

&lt;p&gt;My name is &lt;a href="https://www.linkedin.com/in/gergelyszerovay/" rel="noopener noreferrer"&gt;Gergely Szerovay&lt;/a&gt;, I worked as a data scientist and full-stack developer for many years, and I have been working as frontend tech lead, focusing on Angular based frontend development. As part of my role, I'm constantly following how Angular and the frontend development scene in general is evolving. To share my knowledge, I started the &lt;a href="https://angularaddicts.com/" rel="noopener noreferrer"&gt;Angular Addicts&lt;/a&gt; monthly newsletter and publication in 2022, so that I can send you the best resources I come across each month. Whether you are a seasoned Angular Addict or a beginner, I got you covered. Let me know if you would like to be included as a writer. Let’s learn Angular together! &lt;a href="https://www.angularaddicts.com/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; 🔥&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://www.angularaddicts.com/" rel="noopener noreferrer"&gt;Substack (Angular Addicts)&lt;/a&gt;, &lt;a href="https://aiboosted.dev" rel="noopener noreferrer"&gt;Substack (AIBoosted.dev)&lt;/a&gt;, &lt;a href="https://medium.com/@GergelySzerovay" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;, &lt;a href="https://dev.to/gergelyszerovay"&gt;Dev.to&lt;/a&gt;, &lt;a href="https://twitter.com/GergelySzerovay" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/gergelyszerovay/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to learn more about Angular, and how to build AI apps with AI, Typescript, React and Angular!&lt;/p&gt;

&lt;h2&gt;
  
  
  🕹️Previous issues
&lt;/h2&gt;

&lt;p&gt;If you missed the previous issues of the newsletter, you can read them &lt;a href="https://www.angularaddicts.com/t/angular-addicts-monthly" rel="noopener noreferrer"&gt;here&lt;/a&gt;, these are the latest 3 issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.angularaddicts.com/p/angular-addicts-51-a2ui-signal-debouncing" rel="noopener noreferrer"&gt;Angular Addicts #51: spartan/ui 1.0, A2UI, Signal Debouncing &amp;amp; more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.angularaddicts.com/p/angular-addicts-50-angular-22-agentic-deploying" rel="noopener noreferrer"&gt;Angular Addicts #50: Angular 22, Agentic Angular, Deploying to the Cloud &amp;amp; more&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.angularaddicts.com/p/angular-addicts-49-analogjs-25-agentic-angular" rel="noopener noreferrer"&gt;Angular Addicts #49: AnalogJS 2.5, Agentic Angular &amp;amp; more&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📨 Submit your Angular resource
&lt;/h2&gt;

&lt;p&gt;Have you found or written an interesting Angular-related article, tweet or other resource lately? Please let me know here in the comments or send me a DM on &lt;a href="https://twitter.com/gergelyszerovay" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;! I might feature it in the next Angular Addicts issue!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Ng-News 26/19: Angular 22.1</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Sat, 22 Aug 2026 13:27:49 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2619-angular-221-2geb</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2619-angular-221-2geb</guid>
      <description>&lt;p&gt;Angular 22.1 adds a custom &lt;strong&gt;&lt;code&gt;set&lt;/code&gt; function for &lt;code&gt;linkedSignal&lt;/code&gt;&lt;/strong&gt;. It gives us something like two-way binding between signals while keeping one signal as the source of truth.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/ai_LqkUXmDE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular 22.1
&lt;/h2&gt;

&lt;p&gt;Angular 22.1 is the first minor release in the Angular 22 range. With Angular's yearly major release cycle, we can expect multiple minor releases during the year.&lt;/p&gt;

&lt;p&gt;As a minor release, 22.1 can introduce new features without breaking existing applications. The main feature for this episode is the custom &lt;code&gt;set&lt;/code&gt; function of &lt;code&gt;linkedSignal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Until now, &lt;code&gt;linkedSignal&lt;/code&gt; could derive a writable value from another signal. With the custom setter, writing to that linked value can also update the source signal.&lt;/p&gt;

&lt;p&gt;That gives us something like two-way binding between signals.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/releases/tag/22.1.0" rel="noopener noreferrer"&gt;Angular 22.1 release notes&lt;/a&gt;&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://angular.dev/reference/releases" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fangular.dev%2Fassets%2Fimages%2Fng-image.jpg" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://angular.dev/reference/releases" rel="noopener noreferrer" class="c-link"&gt;
            Versioning and releases • Angular
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            The web development framework for building modern apps.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fangular.dev%2Fassets%2Ficons%2Ffavicon-48x48.png" width="48" height="48"&gt;
          angular.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  A currency converter in both directions
&lt;/h2&gt;

&lt;p&gt;Consider a currency converter with two input fields: one for euros and another for dollars.&lt;/p&gt;

&lt;p&gt;When the user changes the euro value, the dollar value should update immediately. The same should work in the other direction: changing dollars should update euros.&lt;/p&gt;

&lt;p&gt;The euro signal remains the source of truth. The dollar signal is linked to it and derives its value using the exchange rate.&lt;/p&gt;

&lt;p&gt;Before Angular 22.1, the other direction required an &lt;code&gt;effect&lt;/code&gt;. The effect observed changes to the dollar value and wrote the converted result back to the euro signal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before: synchronizing with an effect
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;linkedSignal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;untracked&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FormField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;required&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/forms/signals&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;FormField&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;main class="mx-auto mt-16 grid max-w-md gap-4 p-4"&amp;gt;
      &amp;lt;h1 class="text-2xl font-semibold"&amp;gt;EUR ↔ USD&amp;lt;/h1&amp;gt;
      &amp;lt;label class="grid gap-1 text-sm"&amp;gt;
        EUR
        &amp;lt;input class="rounded border p-2" [formField]="eurForm" type="number" step="0.01" /&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;label class="grid gap-1 text-sm"&amp;gt;
        USD
        &amp;lt;input class="rounded border p-2" [formField]="usdForm" type="number" step="0.01" /&amp;gt;
      &amp;lt;/label&amp;gt;

      &amp;lt;button
        class="cursor-pointer rounded bg-blue-600 px-4 py-2 font-medium text-white hover:bg-blue-700"
        (click)="resetEur()"
      &amp;gt;
        Set USD to 100
      &amp;lt;/button&amp;gt;
    &amp;lt;/main&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;eurValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;eurForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;usdValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;linkedSignal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;computation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;toMoney&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;usdForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usdValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;usdForm&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="nf"&gt;untracked&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;toMoney&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1.16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;eur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eur&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;resetEur&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usdValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`USD &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;usdValue&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt; are in EUR &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;toMoney&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The forward direction already belongs to &lt;code&gt;linkedSignal&lt;/code&gt;: whenever &lt;code&gt;eurValue&lt;/code&gt; changes, the computation derives the dollar value synchronously.&lt;/p&gt;

&lt;p&gt;The reverse direction needs more machinery. The &lt;code&gt;effect&lt;/code&gt; observes the dollar form, &lt;code&gt;untracked&lt;/code&gt; prevents the write to &lt;code&gt;eurValue&lt;/code&gt; from becoming another dependency, and the equality check avoids an unnecessary update.&lt;/p&gt;

&lt;p&gt;There is another difference: effects run asynchronously. If code sets the dollar value and reads the euro value immediately afterwards, it can still see the old euro value until the effect runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  After: writing back with linkedSignal
&lt;/h2&gt;

&lt;p&gt;Angular 22.1 allows &lt;code&gt;linkedSignal&lt;/code&gt; to define what should happen when someone calls &lt;code&gt;set&lt;/code&gt; or &lt;code&gt;update&lt;/code&gt; on it. The write-back logic can therefore live directly beside the computation.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;FormField&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;main class="mx-auto mt-16 grid max-w-md gap-4 p-4"&amp;gt;
      &amp;lt;h1 class="text-2xl font-semibold"&amp;gt;EUR ↔ USD&amp;lt;/h1&amp;gt;
      &amp;lt;label class="grid gap-1 text-sm"&amp;gt;
        EUR
        &amp;lt;input class="rounded border p-2" [formField]="eurForm" type="number" step="0.01" /&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;label class="grid gap-1 text-sm"&amp;gt;
        USD
        &amp;lt;input class="rounded border p-2" [formField]="usdForm" type="number" step="0.01" /&amp;gt;
      &amp;lt;/label&amp;gt;

      &amp;lt;button
        class="cursor-pointer rounded bg-blue-600 px-4 py-2 font-medium text-white hover:bg-blue-700"
        (click)="resetEur()"
      &amp;gt;
        Set USD to 100
      &amp;lt;/button&amp;gt;
    &amp;lt;/main&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;eurValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;eurForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;usdValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;linkedSignal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;computation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;toMoney&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;toMoney&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;usdValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1.16&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;usdForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usdValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="nf"&gt;resetEur&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usdValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`USD &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;usdValue&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt; are in EUR &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eurValue&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;toMoney&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;effect&lt;/code&gt;, &lt;code&gt;untracked&lt;/code&gt;, and constructor disappear. The &lt;code&gt;linkedSignal&lt;/code&gt; now owns both directions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;computation&lt;/code&gt; derives dollars whenever the euro source changes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;set&lt;/code&gt; handles explicit writes to the dollar signal and writes back to the euro source.&lt;/li&gt;
&lt;li&gt;The source update causes the linked value to be recomputed synchronously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a smaller implementation in which the read and write relationship is declared in one place.&lt;/p&gt;

&lt;h2&gt;
  
  
  A custom setter is not a general-purpose effect
&lt;/h2&gt;

&lt;p&gt;The custom &lt;code&gt;set&lt;/code&gt; function runs whenever code explicitly writes to the linked signal. That makes it powerful enough to execute other logic and react to multiple synchronous writes individually.&lt;/p&gt;

&lt;p&gt;Technically, that could be used to work around the glitch-free behavior of an &lt;code&gt;effect&lt;/code&gt;. But that is not the intended pattern. The custom setter is most useful when it expresses how a write to derived state should update its source of truth.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The Angular pattern that needs no Provider</title>
      <dc:creator>Michele Stieven</dc:creator>
      <pubDate>Sun, 16 Aug 2026 22:00:00 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/the-angular-pattern-that-needs-no-provider-2ee4</link>
      <guid>https://dev.to/playfulprogramming-angular/the-angular-pattern-that-needs-no-provider-2ee4</guid>
      <description>&lt;p&gt;Services are often the default abstraction for reusable Angular logic. But what if the logic is local to a component, depends on its injection context, and does not represent shared application state?&lt;/p&gt;

&lt;p&gt;Consider a dashboard widget that knows whether its host element is currently visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-dashboard-widget&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;p&amp;gt;{{ visible() ? 'Awake' : 'Sleeping' }}&amp;lt;/p&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;injectVisibility&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That information can be used to avoid work the user cannot currently see.&lt;/p&gt;

&lt;p&gt;For example, we can avoid creating an expensive part of the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@if (visible()) {
  &lt;span class="nt"&gt;&amp;lt;app-expensive-chart&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or pause and resume an asynchronous process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;toObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;switchMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;visible&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;switchMap&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadStatistics&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EMPTY&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same pattern can suspend polling, animations, data transformations or expensive visualizations while the component is outside the viewport.&lt;/p&gt;

&lt;p&gt;There is no directive in the template, no lifecycle hook and, most importantly, no provider to configure.&lt;/p&gt;

&lt;p&gt;Let’s see how we get there.&lt;/p&gt;

&lt;h2&gt;
  
  
  The component-scoped service
&lt;/h2&gt;

&lt;p&gt;A first solution could be a service that injects the component’s &lt;code&gt;ElementRef&lt;/code&gt;, creates an &lt;code&gt;IntersectionObserver&lt;/code&gt; and exposes the result as a Signal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VisibilityService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;destroyRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DestroyRef&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asReadonly&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;isIntersecting&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destroyRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the service to resolve the correct host element, however, it must be created in the component’s element injector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;VisibilityService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;VisibilityService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, but the API has a hidden requirement: every consumer must remember to declare the provider.&lt;/p&gt;

&lt;p&gt;Forget it, and the feature stops working.&lt;/p&gt;

&lt;p&gt;A root service would not solve the problem either. A singleton has no single component host associated with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The host directive
&lt;/h2&gt;

&lt;p&gt;A host directive models the responsibility more accurately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;hostDirectives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;VisibilityDirective&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;VisibilityDirective&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The behavior is nicely encapsulated, but we still have metadata boilerplate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;hostDirectives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;VisibilityDirective&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For behavior that should also be selectable from a template, this is perfectly reasonable. But our component only needs a contextual value: a Signal tied to its own host and lifecycle.&lt;/p&gt;

&lt;p&gt;Do we really need another injectable instance for that?&lt;/p&gt;

&lt;h2&gt;
  
  
  A custom inject function
&lt;/h2&gt;

&lt;p&gt;Angular’s &lt;code&gt;inject()&lt;/code&gt; API is not limited to services. It can also be used inside a function called while an injection context is active, for example during a component field initializer.&lt;/p&gt;

&lt;p&gt;That lets us implement the entire feature as a function:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;injectVisibility&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IntersectionObserverInit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;assertInInjectionContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;injectVisibility&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;destroyRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DestroyRef&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;isIntersecting&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;destroyRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asReadonly&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-dashboard-widget&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;p&amp;gt;{{ visible() ? 'Awake' : 'Sleeping' }}&amp;lt;/p&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;injectVisibility&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;rootMargin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;200px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;finds the consumer’s host element;&lt;/li&gt;
&lt;li&gt;creates private state for that consumer;&lt;/li&gt;
&lt;li&gt;connects the cleanup to its lifecycle;&lt;/li&gt;
&lt;li&gt;returns a normal readonly Signal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No service instance or component metadata is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the call location matters
&lt;/h2&gt;

&lt;p&gt;This works because field initializers run while Angular is creating the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;injectVisibility&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling the same function later does not work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;startObserving&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;injectVisibility&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Error&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By then, the component creation context has ended. &lt;code&gt;assertInInjectionContext()&lt;/code&gt; makes this constraint immediately clear to consumers of the API.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you use this pattern?
&lt;/h2&gt;

&lt;p&gt;A custom inject function is a good fit when the feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;depends on the caller’s injection context;&lt;/li&gt;
&lt;li&gt;creates state local to each consumer;&lt;/li&gt;
&lt;li&gt;needs contextual dependencies such as &lt;code&gt;ElementRef&lt;/code&gt; or &lt;code&gt;DestroyRef&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;does not represent a shared service;&lt;/li&gt;
&lt;li&gt;can expose its result through an ordinary value, Signal or Observable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A service remains the better abstraction when it has shared state, a meaningful identity, or implementations that consumers need to replace through dependency injection.&lt;/p&gt;

&lt;p&gt;The important distinction is not whether some code uses Angular DI.&lt;/p&gt;

&lt;p&gt;It is whether that code needs to be an injectable object.&lt;/p&gt;

&lt;p&gt;Sometimes the cleanest injectable Angular API is just a function.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Ng-News 26/18: Angular Annual Releases, CopilotKit Integration</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Thu, 06 Aug 2026 18:27:06 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2618-angular-annual-releases-copilotkit-integration-22hk</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2618-angular-annual-releases-copilotkit-integration-22hk</guid>
      <description>&lt;p&gt;Angular is moving to one major release per year, and CopilotKit for Angular is now officially available.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/bU8i0LHCyvQ"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Release Cadence
&lt;/h2&gt;

&lt;p&gt;The Angular team decided to switch the release interval of major versions from half a year to one year. That is effective immediately and it also means that we won't get Angular 23 later this year, but in May or early June 2027.&lt;/p&gt;

&lt;p&gt;That does not mean that new features land later, because adding new features is also allowed in minor versions. The same is also true when it comes to upgrading a certain feature from experimental or developer preview status.&lt;/p&gt;

&lt;p&gt;What changes with the major is the amount of breaking changes. They can only now happen once per year. According to the Angular team, the half-year pace was reported to be an issue for enterprises. One also has to say that one major per year also makes it easier for library developers because the amount of work for updating to the new Angular major is now half the work.&lt;/p&gt;

&lt;p&gt;Speaking of minor releases, version 22.1 was already released and will be covered in the next episode. We can expect 4-6 minor releases instead of a maximum of three as it was before.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://angular.dev/reference/releases" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fangular.dev%2Fassets%2Fimages%2Fng-image.jpg" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://angular.dev/reference/releases" rel="noopener noreferrer" class="c-link"&gt;
            Versioning and releases • Angular
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            The web development framework for building modern apps.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fangular.dev%2Fassets%2Ficons%2Ffavicon-48x48.png" width="48" height="48"&gt;
          angular.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  CopilotKit for Angular
&lt;/h2&gt;

&lt;p&gt;CopilotKit is behind the protocol AG-UI, which is the foundation for agent-driven UIs, including dynamic UI generated at runtime by AI - formats like A2UI run on top of it.&lt;/p&gt;

&lt;p&gt;Their Angular support was not open source, but that changed. The code went public in June, followed by the official announcement in July.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For ng-news there are strict rules and one of them is no self-promotion, unless the speaker is part of a team, which is the case here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The implementation for Angular was done in collaboration with Soverius AI, which is now maintaining the Angular part. Soverius AI consists of Murat Sari and me, Rainer Hahnekamp.&lt;/p&gt;

&lt;p&gt;The Angular integration is part of the CopilotKit repository. The announcement blog links to a demo application which showcases several features, like tool calling, A2UI, Generative UI, and more.&lt;/p&gt;

&lt;p&gt;Other content creators have already updated their content. For example, Manfred Steyer with his article series on Agentic UI.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://www.copilotkit.ai/blog/copilotkit-for-angular" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;copilotkit.ai&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://soverius.ai/blog/soverius-ai-is-now-maintaining-copilotkit-for-angular" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;soverius.ai&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.angulararchitects.io/en/blog/integrating-a2ui-with-ag-ui-in-angular/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.angulararchitects.io%2Fwp-content%2Fuploads%2F2026%2F05%2Fseries-1024x536.png" height="419" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.angulararchitects.io/en/blog/integrating-a2ui-with-ag-ui-in-angular/" rel="noopener noreferrer" class="c-link"&gt;
            Integrating A2UI with AG-UI and CopilotKit in Angular - ANGULARarchitects
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.angulararchitects.io%2Fwp-content%2Fuploads%2F2024%2F01%2Fcropped-2023_Angular_Architects_FavIcon-32x32.png" width="32" height="32"&gt;
          angulararchitects.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>angular</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
