<?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: ng-news</title>
    <description>The latest articles on DEV Community by ng-news (@ng_news).</description>
    <link>https://dev.to/ng_news</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%2Fuser%2Fprofile_image%2F949656%2F1ae20358-2151-4d75-958a-deb7a52cc8de.png</url>
      <title>DEV Community: ng-news</title>
      <link>https://dev.to/ng_news</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ng_news"/>
    <language>en</language>
    <item>
      <title>Ng-News 26/16: OpenNG Foundation, spartan/ui</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Thu, 02 Jul 2026 21:47:45 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2616-openng-foundation-spartanui-1aim</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2616-openng-foundation-spartanui-1aim</guid>
      <description>&lt;p&gt;OpenNG Foundation and spartan/ui 1.0 are the headline topics this week: a new home for libraries like Spectator and Elf, and spartan/ui, a stable shadcn-inspired component library for Angular.&lt;/p&gt;

&lt;p&gt;Also in brief: Storybook's Angular modernization through AnalogJS, the end of ng-conf, and AI Dev Craft in Las Vegas.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  OpenNG Foundation
&lt;/h2&gt;

&lt;p&gt;Maintaining open-source libraries is hard work. Developers often do it in their spare time, committing to years of maintenance, adding new features, and responding to user requests.&lt;/p&gt;

&lt;p&gt;Last episode, we reported that the ngneat organization was taken down for unknown reasons. While we still don't know why it happened, a new home has emerged for its popular libraries like Spectator and Elf: the OpenNG Foundation.&lt;/p&gt;

&lt;p&gt;Gerome Grignon, known for CanIUseAngular and as the organizer of Ng-Baguette, announced the foundation, which is already hosting these libraries. Alongside Gerome, the current OpenNG team also includes Dominic Bachmann, organizer of Angular Lucerne and author of the angular-typed-router library.&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://github.com/openng-foundation" 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%2Favatars.githubusercontent.com%2Fu%2F294824923%3Fs%3D280%26v%3D4" height="280" class="m-0" width="280"&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://github.com/openng-foundation" rel="noopener noreferrer" class="c-link"&gt;
            OpenNG Foundation · GitHub
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            OpenNG Foundation has 8 repositories available. Follow their code on GitHub.
          &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%2Fgithub.githubassets.com%2Ffavicons%2Ffavicon.svg" width="32" height="32"&gt;
          github.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  spartan/ui 1.0
&lt;/h2&gt;

&lt;p&gt;spartan/ui has officially released its 1.0 version. It provides an "accessible, production-ready library of more than 55 components" with fully customizable styling.&lt;/p&gt;

&lt;p&gt;After debuting in August 2023 with 30 primitives, it now reaches stable in 2026 with a modern architecture built around signals, standalone components, zoneless change detection, and SSR. Originally initiated by Robin Götz, a full team quickly formed around the project.&lt;/p&gt;

&lt;p&gt;spartan/ui can be seen as the Angular equivalent to shadcn/ui, famous for its customizability. While similar open-source alternatives exist, spartan/ui was the pioneer and has a proven track record of active maintenance over the years.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/playfulprogramming-angular/announcing-spartanui-10-546o" class="crayons-story__hidden-navigation-link"&gt;Announcing spartan/ui 1.0&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="/playfulprogramming-angular"&gt;
            &lt;img alt="Playful Programming Angular 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%2F3316%2F612534f5-7bba-4bfe-8455-998219bc57cf.png" class="crayons-logo__image" width="800" height="800"&gt;
          &lt;/a&gt;

          &lt;a href="/goetzrobin" 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%2F961549%2F3c98ffe5-8d8b-4db1-827a-de8c63c25444.jpeg" alt="goetzrobin profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/goetzrobin" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Robin Goetz
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Robin Goetz
                
              
              &lt;div id="story-author-preview-content-3974106" 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="/goetzrobin" 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%2F961549%2F3c98ffe5-8d8b-4db1-827a-de8c63c25444.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Robin Goetz&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="/playfulprogramming-angular" class="crayons-story__secondary fw-medium"&gt;Playful Programming Angular&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/playfulprogramming-angular/announcing-spartanui-10-546o" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 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/playfulprogramming-angular/announcing-spartanui-10-546o" id="article-link-3974106"&gt;
          Announcing spartan/ui 1.0
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&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/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/playfulprogramming-angular/announcing-spartanui-10-546o" 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/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;8&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/playfulprogramming-angular/announcing-spartanui-10-546o#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;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

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

&lt;/div&gt;


&lt;h2&gt;
  
  
  AnalogJS in Storybook
&lt;/h2&gt;

&lt;p&gt;Storybook’s Angular integration is getting a modernization, and it is all thanks to AnalogJS.&lt;/p&gt;

&lt;p&gt;While modern versions of the Angular CLI use Vite under the hood as a development server, it remains a "black box." The Angular CLI is still the one managing the compilation. Because the CLI itself is not a Vite plugin, it cannot be easily plugged into other modern tools.&lt;/p&gt;

&lt;p&gt;And that's the issue for Storybook, Vitest, but also others. They are designed to support any framework that presents itself as a Vite plugin.&lt;/p&gt;

&lt;p&gt;AnalogJS, founded and maintained by Brandon Roberts, solves this by doing exactly that. It fully decouples Angular from the CLI's build pipeline and exposes it as a standard Vite plugin. Just activate it, and these modern tools can suddenly compile and serve Angular components out of the box without any Angular-specific configuration. It just works.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2067695792106705118-982" src="https://platform.twitter.com/embed/Tweet.html?id=2067695792106705118"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2067695792106705118-982');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2067695792106705118&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  ng-conf is ending
&lt;/h2&gt;

&lt;p&gt;ng-conf is ending.&lt;/p&gt;

&lt;p&gt;ng-conf was the first Angular conference, going back to 2014 with AngularJS, and it continued through to the modern Angular era all the way through 2025. This also means that there is no US-based Angular conference anymore.&lt;/p&gt;

&lt;p&gt;In its place, a new conference called AI Dev Craft will debut in October in Las Vegas, with a call for speakers open.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2071616309742453054-891" src="https://platform.twitter.com/embed/Tweet.html?id=2071616309742453054"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2071616309742453054-891');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2071616309742453054&amp;amp;theme=dark"
  }



&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ng-News 26/15: Angular 22</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Tue, 23 Jun 2026 19:13:29 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2615-angular-22-23o0</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2615-angular-22-23o0</guid>
      <description>&lt;p&gt;&lt;strong&gt;Angular 22 stable resources and Signal Forms&lt;/strong&gt; are the headline topics, together with new dependency injection APIs such as &lt;strong&gt;&lt;code&gt;@Service&lt;/code&gt; and &lt;code&gt;injectAsync&lt;/code&gt;&lt;/strong&gt;. Also in brief: &lt;code&gt;debounced()&lt;/code&gt;, Vitest migration support, &lt;code&gt;ChangeDetectionStrategy.Eager&lt;/code&gt;, WebMCP, community write-ups, and the ng-neat recovery.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Stable resources and Signal Forms
&lt;/h2&gt;

&lt;p&gt;Angular 22 is out. Probably the most outstanding feature is the stabilization of the resource and the Signal Forms. There's much more but let's start with these two.&lt;/p&gt;

&lt;p&gt;Resources, that are three functions &lt;code&gt;resource()&lt;/code&gt;, &lt;code&gt;rxResource()&lt;/code&gt; and &lt;code&gt;httpResource()&lt;/code&gt;, have been introduced during Angular 19. There were some significant changes in Angular 20, and then in Angular 21 we got the snapshot feature. Resources have been experimental all the time, and after almost 1.5 years, they leave experimental status and become stable.&lt;/p&gt;

&lt;p&gt;Similar story for Signal Forms, but at a just faster pace. They were introduced in 21 and are now also stable, so no developer preview either.&lt;/p&gt;

&lt;p&gt;So in some way, these are features we already knew and some of us were already using quite successfully.&lt;/p&gt;

&lt;p&gt;And let's not forget, also &lt;code&gt;@angular/aria&lt;/code&gt;, the headless design system also became stable.&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/announcing-angular-v22-c52bb83a4664" 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;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/06/03/what-is-new-angular-22.0" 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%2Flogo.svg" height="43" class="m-0" width="183"&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/06/03/what-is-new-angular-22.0" rel="noopener noreferrer" class="c-link"&gt;
            What's new in Angular 22.0? - Ninja Squad
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Angular 22.0 is out!
          &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;h2&gt;
  
  
  &lt;code&gt;@Service&lt;/code&gt;, &lt;code&gt;injectAsync&lt;/code&gt;, and &lt;code&gt;debounced()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;But, there are new features as well.&lt;/p&gt;

&lt;p&gt;For one, we have the &lt;code&gt;@Service&lt;/code&gt; decorator. That means it is on one side a shortcut for &lt;code&gt;@Injectable({ providedIn: 'root' })&lt;/code&gt; and on the other prevents using dependency injection via the constructor. Instead of constructor-based DI, you should go with the &lt;code&gt;inject&lt;/code&gt; function and there is a dedicated migration available (&lt;code&gt;ng generate @angular/core:inject&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="nd"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NewsletterClient&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;httpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Observable&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="k"&gt;return&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;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://some.host.com/newsletter/subscribe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&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;Another feature for dependency injection is the asynchronous injector. So the value returned by &lt;code&gt;injectAsync&lt;/code&gt; is not the service instance itself - you call it when you need the service and await the result. Why do we need it? Well, same thing why we do lazy loading in the router. We only want to load when it is actually needed.&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;NewsletterPage&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;newsletterModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;newsletterClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;injectAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;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;./newsletter-client&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;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;newsletterForm&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;newsletterModel&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="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;submission&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;action&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newsletterClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
          &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&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;newsletterModel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;email&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;So you won't use &lt;code&gt;injectAsync&lt;/code&gt; when you need the service immediately but more when a user clicks on something or some later events. The service needs to be &lt;code&gt;providedIn: 'root'&lt;/code&gt;. So it's best if you already apply the new &lt;code&gt;@Service&lt;/code&gt; decorator.&lt;/p&gt;



&lt;p&gt;And we have a debounced function. You give it a signal and a debounce time, and you are getting back a resource. Debouncing means, when the signal's value changes, the value in the derived resource would wait for the defined period of time until a new value comes. If that's not the case, then the resource will take on that value, and if not, the debouncing starts again.&lt;/p&gt;

&lt;p&gt;As every Signal has an initial value, the debouncing for the first value doesn't happen.&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-debounced&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;`Value {{ debouncedCounter.value() }}`&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;DebouncedPage&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;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;debouncedCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;debounced&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;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;600&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;setTimeout&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;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&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;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&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;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&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;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&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;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&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;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;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;`value updated &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;debouncedCounter&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="s2"&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;debounced()&lt;/code&gt; is experimental. &lt;code&gt;@Service&lt;/code&gt; and &lt;code&gt;injectAsync&lt;/code&gt; are not.&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://angular.love/angular-22-key-features-and-changes" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;angular.love&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/angular-22-the-most-important-new-features-at-a-glance/" 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%2F06%2Fen.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/angular-22-the-most-important-new-features-at-a-glance/" rel="noopener noreferrer" class="c-link"&gt;
            Angular 22: The Most Important New Features at a Glance - ANGULARarchitects
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Angular 22 stabilizes the Resource API and Signal Forms, makes OnPush the default change detection strategy, and brings @Service, injectAsync, debounced, as well as numerous template and router improvements. This article shows the relevant updates using concrete examples.
          &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%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;


&lt;h2&gt;
  
  
  Vitest and change detection
&lt;/h2&gt;

&lt;p&gt;In Angular 21, we've received Vitest as the new default testing framework. It was not possible to easily migrate because a lot of us were using &lt;code&gt;fakeAsync&lt;/code&gt; or &lt;code&gt;waitForAsync&lt;/code&gt; to manage asynchronous tasks in tests. With Angular 22, that is possible again, but remember, &lt;code&gt;fakeAsync&lt;/code&gt; and &lt;code&gt;waitForAsync&lt;/code&gt; depend on zone.js. So if you have plans to move to zoneless or are already there, it is not an option.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;ng update&lt;/code&gt;, your components which are not OnPush will get a &lt;code&gt;ChangeDetectionStrategy.Eager&lt;/code&gt;. That's the new alias for the old Default value, because default is not OnPush. Speaking of zoneless, if you want to migrate, staying with zone.js and moving all your components to OnPush as an intermediate step is a good approach.&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/announcing-angular-v22-c52bb83a4664" 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;h2&gt;
  
  
  WebMCP
&lt;/h2&gt;

&lt;p&gt;Also in terms of AI, there is experimental support for WebMCP. That means an agent can connect to your web application and can execute certain tool calls. That means, you in Angular have to expose calls to services with a description and so on, and then if the browser supports it, the agent can call them. So it is not necessary anymore that the browser has to read and interact with the DOM.&lt;/p&gt;

&lt;p&gt;WebMCP is still in development, but we can expect to hear more from it in the future. There is also a feature which sets up forms for WebMCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community content
&lt;/h2&gt;

&lt;p&gt;As always, there is a lot of community content out there. We had a release video, a release blog and Mark Thompson, Angular's DevRel, was also guest at the Angular Plus Show.&lt;/p&gt;

&lt;p&gt;For this episode, we additionally used the blogs from Cedric Exbrayat from Ninja Squad, Manfred Steyer from Angular Architects, and Mateusz Stefańczyk from House of Angular.&lt;/p&gt;

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

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/CnQr8bAYKKY"&gt;
  &lt;/iframe&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://blog.ninja-squad.com/2026/06/03/what-is-new-angular-22.0" 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%2Flogo.svg" height="43" class="m-0" width="183"&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/06/03/what-is-new-angular-22.0" rel="noopener noreferrer" class="c-link"&gt;
            What's new in Angular 22.0? - Ninja Squad
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Angular 22.0 is out!
          &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;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://angular.love/angular-22-key-features-and-changes" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;angular.love&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/angular-22-the-most-important-new-features-at-a-glance/" 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%2F06%2Fen.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/angular-22-the-most-important-new-features-at-a-glance/" rel="noopener noreferrer" class="c-link"&gt;
            Angular 22: The Most Important New Features at a Glance - ANGULARarchitects
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Angular 22 stabilizes the Resource API and Signal Forms, makes OnPush the default change detection strategy, and brings @Service, injectAsync, debounced, as well as numerous template and router improvements. This article shows the relevant updates using concrete examples.
          &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%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;


&lt;h2&gt;
  
  
  ng-neat GitHub
&lt;/h2&gt;

&lt;p&gt;Last but not least, a very important information. Last weekend, the popular ng-neat organization was removed from GitHub. That contained widely used libraries, like Elf for state management and Spectator for testing. Before that, members of the organization were also removed. At the moment, we don't know why because there was no official communication from the owner.&lt;/p&gt;

&lt;p&gt;What is important though, that most of the libraries have been recovered and found their way back to GitHub under a new organization called ngneat-archive. We will keep you updated on this topic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reddit.com/r/angular/comments/1txtp35/" rel="noopener noreferrer"&gt;Reddit thread&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>angular</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Ng-News 26/14: linkedSignal Write-Back, Error Boundaries</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Tue, 02 Jun 2026 20:55:34 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2614-linkedsignal-write-back-error-boundaries-5ghb</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2614-linkedsignal-write-back-error-boundaries-5ghb</guid>
      <description>&lt;p&gt;&lt;strong&gt;Angular 22 stabilization&lt;/strong&gt; (resources, Signal Forms, &lt;code&gt;@angular/aria&lt;/code&gt;) and &lt;strong&gt;compiler ABI stability across patch versions&lt;/strong&gt; for micro frontends are the headline items this week. Also in brief: &lt;code&gt;linkedSignal&lt;/code&gt;'s &lt;code&gt;set&lt;/code&gt; option and NgRx's reverted &lt;code&gt;delegatedSignal&lt;/code&gt;, plus error boundaries from Google I/O.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Angular 22 stabilization
&lt;/h2&gt;

&lt;p&gt;The release of Angular 22 is getting closer, and we are also getting more and more information about the changes but also what awaits us beyond Angular 22.&lt;/p&gt;

&lt;p&gt;We already know that Angular 22 will make a lot of features stable. That is resources, Signal Forms, but also &lt;code&gt;@angular/aria&lt;/code&gt;. Stable means no breaking changes within majors.&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;
  
  
  Compiler ABI and micro frontends
&lt;/h2&gt;

&lt;p&gt;Another feature was announced, and it will be a happy message for anyone who's using micro frontends via Native Federation or Module Federation. Until now, whenever you loaded another Angular application/micro frontend during runtime, you had to make sure that it has been compiled with exactly the same version as the host application.&lt;/p&gt;

&lt;p&gt;Why? Because the compiled Angular code was never part of the public API and didn't follow semantic versioning, which means the Angular team could introduce breaking changes within patch versions.&lt;/p&gt;

&lt;p&gt;That is going to change. Breaking changes within a major can still happen in minors, but not in patch versions.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/angular/angular/pull/68623" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        docs: establish compiler abi stability across patch versions
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#68623&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/alxhub" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F4175141%3Fv%3D4" alt="alxhub avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/alxhub" rel="noopener noreferrer"&gt;alxhub&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/angular/angular/pull/68623" rel="noopener noreferrer"&gt;&lt;time&gt;May 07, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Define the new policy that the compiler ABI (the internal runtime APIs called by compiler-generated code) is stable across patch versions within the same minor version. This update unblocks microfrontend use cases and safer sharing of the Angular runtime across independent builds.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/angular/angular/pull/68623" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  linkedSignal &lt;code&gt;set&lt;/code&gt; and delegatedSignal
&lt;/h2&gt;

&lt;p&gt;In former episodes, we've already touched upon the need for a new Signal type, which is like &lt;code&gt;linkedSignal&lt;/code&gt;, that derives the value from another Signal, but is not writable. At the same time though, it should be possible to have an option to write back to the original Signal.&lt;/p&gt;

&lt;p&gt;That feature exists already for Signal Forms under the name &lt;code&gt;DeepSignal&lt;/code&gt;, but it is only internal. And because there is a need for it for us as well, NgRx, a state management library, was about to introduce that as &lt;code&gt;delegatedSignal&lt;/code&gt; in NgRx 22, but it is not going to happen and the existing commit was reverted.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;linkedSignal&lt;/code&gt; itself will get a &lt;code&gt;set&lt;/code&gt; option, which allows you to write back to the original Signal. So in some way what the &lt;code&gt;delegatedSignal&lt;/code&gt; would have done will be part of the &lt;code&gt;linkedSignal&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;The PR has a label for minor version, which means Angular 22.1. Last summer, the difference between 20.0 and 20.1 was around 6 weeks. Given that Angular 22 will be released in the week of June 3rd, that means we are looking at a release of mid-July.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/angular/angular/pull/68708" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat(core): add custom set option to linkedSignal
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#68708&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/alxhub" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F4175141%3Fv%3D4" alt="alxhub avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/alxhub" rel="noopener noreferrer"&gt;alxhub&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/angular/angular/pull/68708" rel="noopener noreferrer"&gt;&lt;time&gt;May 13, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Introduce a custom &lt;code&gt;set&lt;/code&gt; option in &lt;code&gt;linkedSignal&lt;/code&gt; options to allow overriding and customizing the default write-back behavior of writable signals. This lets developers route updates back to the source of truth (e.g., converting Fahrenheit back to Celsius) or perform other side effects like updating properties inside a parent signal.&lt;/p&gt;
&lt;p&gt;Additionally, the custom callback receives the standard signal setter as its second parameter (&lt;code&gt;rawSet&lt;/code&gt;) to allow direct internal mutation if desired.&lt;/p&gt;
&lt;p&gt;TAG=agy
CONV=addbb5c4-4233-49e8-b844-6f732d7d5c72&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;PR Checklist&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Please check if your PR fulfills the following requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ ] The commit message follows our guidelines: &lt;a href="https://github.com/angular/angular/blob/main/contributing-docs/commit-message-guidelines.md" rel="noopener noreferrer"&gt;https://github.com/angular/angular/blob/main/contributing-docs/commit-message-guidelines.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Tests for the changes have been added (for bug fixes / features)&lt;/li&gt;
&lt;li&gt;[ ] Docs have been added / updated (for bug fixes / features)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;PR Type&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;What kind of change does this PR introduce?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Bugfix&lt;/li&gt;
&lt;li&gt;[ ] Feature&lt;/li&gt;
&lt;li&gt;[ ] Code style update (formatting, local variables)&lt;/li&gt;
&lt;li&gt;[ ] Refactoring (no functional changes, no api changes)&lt;/li&gt;
&lt;li&gt;[ ] Build related changes&lt;/li&gt;
&lt;li&gt;[ ] CI related changes&lt;/li&gt;
&lt;li&gt;[ ] Documentation content changes&lt;/li&gt;
&lt;li&gt;[ ] angular.dev application / infrastructure changes&lt;/li&gt;
&lt;li&gt;[ ] Other... Please describe:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What is the current behavior?&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;Issue Number: N/A&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What is the new behavior?&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Does this PR introduce a breaking change?&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[ ] Yes&lt;/li&gt;
&lt;li&gt;[ ] No&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Other information&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/angular/angular/pull/68708" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/ngrx/platform/pull/5157" rel="noopener noreferrer"&gt;ngrx/platform#5157 — revert delegatedSignal (Angular linkedSignal &lt;code&gt;set&lt;/code&gt; planned)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/ng-news/ng-news-26-11-typescript-6-ngrx-rfcs-delegatedsignal-resource-extensions-b953f0d3cc29" rel="noopener noreferrer"&gt;Ng-News 26/11: TypeScript 6, NgRx RFCs, delegatedSignal&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Google I/O: error boundaries
&lt;/h2&gt;

&lt;p&gt;Google's conference Google I/O also took place, and Mark Thompson, Angular DevRel, gave a talk where, among other things, he introduced an upcoming feature which is called error boundaries.&lt;/p&gt;

&lt;p&gt;You can see it as an elegant try/catch block for the template. Similar to &lt;code&gt;@defer&lt;/code&gt; you wrap parts of the template into &lt;code&gt;@boundary&lt;/code&gt; and if an error occurs, the boundary will catch it and display a fallback. Mark also mentioned that there could be an option to define retry logic for the boundary.&lt;/p&gt;

&lt;p&gt;That will also improve the DX with resources, which throw the error if you access its value.&lt;/p&gt;

&lt;p&gt;It was the first time that we heard about this feature publicly. Mark said that they plan to make it available as developer preview in Q3 this year, which probably means Angular 23.&lt;/p&gt;

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

</description>
      <category>angular</category>
      <category>programming</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Ng-News 26/13: @Service, Native Federation, Angular Feature Lifecycles</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Tue, 05 May 2026 18:13:29 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2613-service-native-federation-angular-feature-lifecycles-1g5f</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2613-service-native-federation-angular-feature-lifecycles-1g5f</guid>
      <description>&lt;p&gt;Angular 22's proposed &lt;strong&gt;&lt;code&gt;@Service&lt;/code&gt; decorator&lt;/strong&gt; and the likely stabilization of the &lt;strong&gt;resource API family&lt;/strong&gt;. Also in brief: Angular feature lifecycle stages, Native Federation v4 changes, and fresh Oxc Angular compiler benchmark context.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Angular 22 preview: &lt;code&gt;@Service&lt;/code&gt; and resource APIs
&lt;/h2&gt;

&lt;p&gt;The release of Angular 22 comes closer, and we are also getting more and more information about the changes.&lt;/p&gt;

&lt;p&gt;For example, we will get a new decorator for services, which will also be called &lt;code&gt;@Service&lt;/code&gt;. What's the difference compared with the existing &lt;code&gt;@Injectable&lt;/code&gt; decorator?&lt;/p&gt;

&lt;p&gt;By default, &lt;code&gt;@Service&lt;/code&gt; will automatically provide the service in root, and you cannot use constructor-based dependency injection anymore, but have to go via the &lt;code&gt;inject&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;And another PR, which is still open, says the resource family, including &lt;code&gt;httpResource&lt;/code&gt;, but also &lt;code&gt;rxResource&lt;/code&gt;, will leave the experimental stage and become stable. So the developer preview gets skipped. One also has to say that we have had the resource APIs for almost 1.5 years now, so it is more than time.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/angular/angular/pull/68195" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat(core): introduce @Service decorator
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#68195&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/crisbeto" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F4450522%3Fv%3D4" alt="crisbeto avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/crisbeto" rel="noopener noreferrer"&gt;crisbeto&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/angular/angular/pull/68195" rel="noopener noreferrer"&gt;&lt;time&gt;Apr 14, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;These changes introduce the new &lt;code&gt;@Service&lt;/code&gt; decorator which is a more ergonomic alternative to &lt;code&gt;@Injectable&lt;/code&gt;. The reason we're adding a new decorator is that &lt;code&gt;@Injectable&lt;/code&gt; has been around since the beginning of Angular and it has a lot of baggage that adds unnecessary overhead for users that generally want to define a singleton service, available in their entire app. The key differences between &lt;code&gt;@Service&lt;/code&gt; and &lt;code&gt;@Injectable&lt;/code&gt; are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;@Service&lt;/code&gt; is &lt;code&gt;providedIn: 'root'&lt;/code&gt; by default. You can opt into providing the service yourself by setting &lt;code&gt;autoProvided: false&lt;/code&gt; on it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@Service&lt;/code&gt; doesn't allow constructor-based injection, only the &lt;code&gt;inject&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@Service&lt;/code&gt; doesn't support the complex type signature of &lt;code&gt;@Injectable&lt;/code&gt; (&lt;code&gt;useClass&lt;/code&gt;, &lt;code&gt;useValue&lt;/code&gt; etc.). Instead it supports a single &lt;code&gt;factory&lt;/code&gt; function.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight highlight-source-ts js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-v"&gt;Service&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'@angular/core'&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-v"&gt;HttpClient&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'@angular/common/http'&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-v"&gt;AuthService&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'./auth'&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

@&lt;span class="pl-v"&gt;Service&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;
&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-k"&gt;class&lt;/span&gt; &lt;span class="pl-smi"&gt;PostService&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-k"&gt;private&lt;/span&gt; &lt;span class="pl-k"&gt;readonly&lt;/span&gt; &lt;span class="pl-c1"&gt;httpClient&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;inject&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-v"&gt;HttpClient&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
  &lt;span class="pl-k"&gt;private&lt;/span&gt; &lt;span class="pl-k"&gt;readonly&lt;/span&gt; &lt;span class="pl-c1"&gt;authService&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;inject&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-v"&gt;AuthService&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

  &lt;span class="pl-en"&gt;getUserPosts&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
    &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-smi"&gt;this&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;httpClient&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;get&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'/api/posts/'&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-smi"&gt;this&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;authService&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;userId&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
  &lt;span class="pl-kos"&gt;}&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/angular/angular/pull/68195" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/angular/angular/pull/68253" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        refactor(core): promote `resource`, `rxResource` &amp;amp; `httpResource` to stable
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#68253&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/JeanMeche" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F1300985%3Fv%3D4" alt="JeanMeche avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/JeanMeche" rel="noopener noreferrer"&gt;JeanMeche&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/angular/angular/pull/68253" rel="noopener noreferrer"&gt;&lt;time&gt;Apr 16, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;The time has come.&lt;/p&gt;
&lt;p&gt;Note: #67382 introduced a breaking change where you could notice some sublte timing change on how &lt;code&gt;value&lt;/code&gt; is set when using &lt;code&gt;rxResource&lt;/code&gt; or a &lt;code&gt;stream&lt;/code&gt; on a &lt;code&gt;resource&lt;/code&gt;&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/angular/angular/pull/68253" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Feature lifecycle stages in Angular
&lt;/h2&gt;

&lt;p&gt;Alejandro Cuba Ruiz wrote on the ng-conf Medium publication about what he calls the five lifecycle stages of an Angular feature: experimental, developer preview, stable, deprecated, and removed. The article is not a secret internal document; it lines up with what we occasionally also hear from the Angular team.&lt;/p&gt;

&lt;p&gt;Experimental means the API can move under minors or patches, so the author argues to keep it out of production and to experiment in isolation. Developer preview is "we like the design, show us real-world pain" - safer than experimental, still not semver-frozen. Stable is the contract: breaking changes belong in majors, with migrations when possible. Deprecated gives you the familiar two-major-version runway, and removed is the point where the code is actually gone.&lt;/p&gt;

&lt;p&gt;He also mentions tooling outside the official docs, for example a "Can I Use Angular Features" grid from Gerome Grignon, which can be handy if you support more than one Angular version.&lt;/p&gt;

&lt;p&gt;Next to experimental, developer preview, and stable, there are also the deprecation and removal stages that Alejandro also covers.&lt;/p&gt;

&lt;p&gt;So quite a sound guide to help you decide if and when you want to use a certain feature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/ngconf/the-5-lifecycle-stages-of-an-angular-feature-c3ecc5529d53" rel="noopener noreferrer"&gt;The 5 lifecycle stages of an Angular feature&lt;/a&gt;&lt;br&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;
  
  
  Native Federation v4 updates
&lt;/h2&gt;

&lt;p&gt;Native Federation is next to Module Federation one of the most used libraries when it comes to building microfrontends in Angular. Native Federation version 4 was released and brings a bunch of updates, whereas the most visible one is a website with a lot of documentation. The GitHub repository was also moved to a new organization, the code is now split into multiple repositories, and an orchestrator that manages the microfrontends takes or will take over the old runtime.&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://native-federation.com/index.html" 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%2Fnative-federation.com%2Fimages%2Fsujet-dark.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://native-federation.com/index.html" rel="noopener noreferrer" class="c-link"&gt;
            Native Federation — Micro Frontends with Web Standards
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A browser-native implementation of Module Federation for building Micro Frontends using web standards like ESM and Import Maps.
          &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%2Fnative-federation.com%2Fimages%2Ffavicon.png" width="256" height="256"&gt;
          native-federation.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Oxc Angular compiler benchmarks and caveats
&lt;/h2&gt;

&lt;p&gt;In a former episode of ng-news, we've already covered Void Zero's experiments on writing the Angular compiler in the Oxidation Compiler, which is built on Rust.&lt;/p&gt;

&lt;p&gt;There is now an official article where they publish official numbers and also give some background information on their development process, which is of course heavily AI-based.&lt;/p&gt;

&lt;p&gt;They describe on the order of two months of work, mainly with Claude Code and Codex, under the steering of experienced engineers - not "the model wrote a compiler overnight," but agents doing large-scale porting and review work once the architecture and guardrails exist.&lt;/p&gt;

&lt;p&gt;The headline numbers are eye-catching: they report on the order of six times faster compiles than the Angular CLI.&lt;/p&gt;

&lt;p&gt;As always, be careful with those numbers, but they could be reasonable. Especially since they omitted some heavy tasks like template type-checking. They also admit that the non-existing type-check is a significant performance booster.&lt;/p&gt;

&lt;p&gt;The compiler is available as a Vite plugin, &lt;code&gt;@oxc-angular/vite&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;VoidZero also writes that the repository will not be maintained long term. In parallel, they note that the Angular team has its own experiments with Oxc.&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://voidzero.dev/posts/oxc-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%2Fvoidzero.dev%2Fcovers%2Foxc-angular-compiler.jpg" height="402" 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://voidzero.dev/posts/oxc-angular-compiler" rel="noopener noreferrer" class="c-link"&gt;
            How we made the Angular Compiler faster using AI | VoidZero
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            How VoidZero built the Oxc Angular Compiler, an AI-powered Angular compiler that achieves up to 20x faster code compiling speed.
          &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;div class="color-secondary fs-s flex items-center"&amp;gt;
        &amp;lt;img
          alt="favicon"
          class="c-embed__favicon m-0 mr-2 radius-0"
          src="https://voidzero.dev/favicon.svg"
          loading="lazy" /&amp;gt;
      voidzero.dev
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/voidzero-dev/oxc-angular-compiler" rel="noopener noreferrer"&gt;voidzero-dev/oxc-angular-compiler&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Ng-News 26/12: Future of Selectorless, Skills vs. MCP, Zoneless Testing</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Fri, 10 Apr 2026 13:22:25 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2612-future-of-selectorless-skills-vs-mcp-zoneless-testing-3gmo</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2612-future-of-selectorless-skills-vs-mcp-zoneless-testing-3gmo</guid>
      <description>&lt;p&gt;Ng-News 26/12 covers the Angular Q&amp;amp;A on selectorless and Skills versus MCP, then zoneless testing and auto tick from the Angular Plus Show.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Angular Q&amp;amp;A: selectorless and Skills vs MCP
&lt;/h2&gt;

&lt;p&gt;The monthly Q&amp;amp;A session featured Mark Thompson as host and Alex Rickabaugh, tech lead of the Angular framework.&lt;/p&gt;

&lt;p&gt;Alex explained why selectorless got downgraded. Selectorless was a planned feature that would have allowed referring to components in a template by using their class name. In the latest roadmap update, that feature was removed.&lt;/p&gt;

&lt;p&gt;According to Alex, selectorless would have been a huge jump. The risk of an AI agent not being able to write modern Angular code was not worth the DX benefits from selectorless. Therefore, that feature is on hold and will be re-evaluated in the future.&lt;/p&gt;

&lt;p&gt;Timestamp: 0:05:50&lt;/p&gt;

&lt;p&gt;Skills and MCPs: According to Alex, Skills are starting to replace MCP tools, because a Skill can tell the agent about certain CLI commands, which can replace a dedicated MCP tool call.&lt;/p&gt;

&lt;p&gt;Timestamp: 23:11&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Zoneless testing and auto tick
&lt;/h2&gt;

&lt;p&gt;The Angular Plus Show published an episode on &lt;strong&gt;zoneless testing&lt;/strong&gt; with Andrew Scott (Angular team), &lt;a class="mentioned-user" href="https://dev.to/younesjd"&gt;@younesjd&lt;/a&gt;, and Rainer Hahnekamp.&lt;/p&gt;

&lt;p&gt;Zoneless tests run outside Zone.js, which clarifies some patterns but means you cannot use &lt;code&gt;fakeAsync&lt;/code&gt; or &lt;code&gt;waitForAsync&lt;/code&gt; in that mode.&lt;/p&gt;

&lt;p&gt;With zoneless, change detection in tests would be triggered like in the application, whereas in zone-based tests, users had to trigger it very often manually via &lt;code&gt;ComponentFixture#detectChanges&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The panel also discussed &lt;strong&gt;auto tick&lt;/strong&gt;, recently released around the time of recording and covered in a prior ng-news segment.&lt;/p&gt;

&lt;p&gt;It can simplify async behavior when timer APIs are faked, but it is not always the first choice: mixing real and fake timers produces confusing failures, and faking timers overrides timing globally and can affect third-party code you do not control.&lt;/p&gt;

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

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

&lt;p&gt;This is a new feature of ng-news. At the end of each article, we are listing all upcoming conferences.&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://angularbelgrade.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%2Fangularbelgrade.org%2Fbanners%2Fng-belgrade-conf-2026.jpg" height="424" 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://angularbelgrade.org/" rel="noopener noreferrer" class="c-link"&gt;
            NG Belgrade Conf 2026
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            NG Belgrade Conf 2026 is the largest Angular conference in the Balkans. It takes place in Belgrade, Serbia, including a Conference Day on May 7th and a Workshop Day on May 8th. Join us to explore the latest trends and best practices in 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%2Fangularbelgrade.org%2Fassets%2Ffavicon-A8dvQfkm.ico" width="256" height="256"&gt;
          angularbelgrade.org
        &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__body flex items-center justify-between"&gt;
        &lt;a href="https://ngbaguette.angulardevs.fr/en/" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;ngbaguette.angulardevs.fr&lt;/span&gt;
          

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


</description>
      <category>angular</category>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ng-News 26/11: TypeScript 6, NgRx RFCs delegatedSignal, Resource Extensions</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Fri, 03 Apr 2026 17:43:23 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2611-typescript-6-ngrx-rfcs-delegatedsignal-resource-extensions-ig6</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2611-typescript-6-ngrx-rfcs-delegatedsignal-resource-extensions-ig6</guid>
      <description>&lt;p&gt;Main topics: &lt;strong&gt;TypeScript 6.0&lt;/strong&gt; and &lt;strong&gt;NgRx&lt;/strong&gt; (RFCs for &lt;code&gt;delegatedSignal&lt;/code&gt; and resource extensions). Also in brief: Martina Kraus on security, debounce for async validators, Alfredo Perez on SpecKit, and Angular Graz on YouTube.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  TypeScript 6.0
&lt;/h2&gt;

&lt;p&gt;TypeScript 6.0 was released and it is going to be the last TypeScript version, written in TypeScript. Officially, TypeScript 6 is seen as the bridge between TypeScript 5 and TypeScript 7 (which will be written in Go). First of all, TypeScript 6 is not yet part of Angular. So you can't make use of those changes yet. Angular 21 supports TypeScript 5.9, but 22 will support TypeScript 6.&lt;/p&gt;

&lt;p&gt;In order to prepare for version 7, TypeScript 6 comes primarily with a lot of deprecations and new default settings, which pay tribute to the modern TypeScript ecosystem.&lt;/p&gt;

&lt;p&gt;For example, ESM is now default module system, the strict mode is enabled and the target is the ECMAScript version with the number of the current last year. By now, that would be ECMAScript 2025.&lt;/p&gt;

&lt;p&gt;When it comes to the deprecation. Target ES5, which was the last version of JavaScript without the class syntax, lambda expressions, Promises, let or const, string interpolation, and much more got deprecated.&lt;/p&gt;

&lt;p&gt;What also went away is the &lt;code&gt;baseUrl&lt;/code&gt; property in the &lt;code&gt;tsconfig.json&lt;/code&gt; file, support for the module systems amd, umd, and systemjs (not sure if our younger colleagues still know what that is) has also gone. You can of course also revert those deprecations, but be aware that in TypeScript 7, that means game over.&lt;/p&gt;

&lt;p&gt;There is an automatic migration tool available, which is marked as experimental.&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://devblogs.microsoft.com/typescript/announcing-typescript-6-0/" 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%2Fdevblogs.microsoft.com%2Ftypescript%2Fwp-content%2Fuploads%2Fsites%2F11%2F2026%2F03%2Fts-6.0-2.png" height="350" class="m-0" width="562"&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://devblogs.microsoft.com/typescript/announcing-typescript-6-0/" rel="noopener noreferrer" class="c-link"&gt;
            Announcing TypeScript 6.0 - TypeScript
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            TypeScript 6.0 is now available! TypeScript 6 is a stepping-stone release, aligning with the upcoming native-speed 7.0 release.
          &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%2Fdevblogs.microsoft.com%2Ftypescript%2Fwp-content%2Fuploads%2Fsites%2F11%2F2018%2F10%2FMicrosoft-Favicon.png" width="18" height="18"&gt;
          devblogs.microsoft.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;There are also new features, and the most prominent one is the introduction of the Temporal API.&lt;/p&gt;

&lt;p&gt;This is a new, built-in date and time API in JavaScript, which can be seen as a full replacement for the old Date object. As that, it provides way more functionality for example handling timezones, a calendar which can be used to reflect Chinese or other calendar systems, immutability and a range of utility functions.&lt;/p&gt;

&lt;p&gt;Some veterans of us might remember the switch to the Date-time API in Java more than 10 years ago. It kind of did the same thing.&lt;/p&gt;

&lt;p&gt;Temporal API has reached stage 4 of the TC39 process, which means it is standardized, finished. That doesn't mean that each platform supports it. The latest version of Chrome, Firefox supports it, but not Safari and also Node.js which means if you use it, you should secure your code with polyfills.&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.typescriptlang.org/play/?target=99&amp;amp;amp;jsx=0&amp;amp;amp;ssl=5&amp;amp;amp;ssc=46&amp;amp;amp;pln=1&amp;amp;amp;pc=1#code/MYewdgzgLgBFIBMCGBPGBeGAVApgWwAcQAnJAGwDoA5EAdwoLKQEswARJKHASQGUB5ABQBKANwAoUJFjQkxKPwBmATRxyMcRKgq1mUABaCA3jDzgDALhgBGADQxkKK9ZgBfMZPDQHzRYo2y8kqqchQArmBQzGSC8I4enpAgZDgUZCAA5oIABgAkRgi+ihSOEK4OqBAw+kgAbjgwBEgQEDgI2WJAA" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;typescriptlang.org&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;br&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;today&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Temporal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plainDateISO&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;startOfYear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;startOfYear&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;today&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;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; days have passed`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  NgRx RFCs
&lt;/h2&gt;

&lt;p&gt;NgRx is the most used library for state management in Angular and official work has begun on supporting resources but also forms. Two RFCs for that have landed.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;delegatedSignal()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The first RFC is related to supporting Signal Forms and it introduces a new Signal type called &lt;code&gt;delegatedSignal&lt;/code&gt;. To the outside it is a writable Signal, but it doesn't store a value. Instead it writes and reads to another Signal. What's the use of it?&lt;/p&gt;

&lt;p&gt;Let's say we have a user object in a Signal, that has two nested properties: &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;address&lt;/code&gt;. &lt;code&gt;name&lt;/code&gt; has &lt;code&gt;firstName&lt;/code&gt; and &lt;code&gt;lastName&lt;/code&gt;, and &lt;code&gt;address&lt;/code&gt; has &lt;code&gt;street&lt;/code&gt; and &lt;code&gt;city&lt;/code&gt;, like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;street&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123 Main St&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Anytown&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;If we have a form, which requires a flattened version of the user object, we would usually create a &lt;code&gt;linkedSignal&lt;/code&gt;. The problem is that changes in the form might be synchronized back to the original Signal. At the moment, the only way would be to use an &lt;code&gt;effect&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="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;``&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;UserPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;street&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Main Street&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;London&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;userFormModel&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;firstname&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;user&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;street&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;user&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;street&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}))&lt;/span&gt;

  &lt;span class="nx"&gt;userForm&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;userFormModel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;syncEffect&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;street&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="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;userFormModel&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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;street&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="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;delegatedSignal&lt;/code&gt; solves this problem by writing synchronously back to the original 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="c1"&gt;// PROTOTYPE!!!&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;delegatedSignal&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;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;computation&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;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;update&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="nx"&gt;T&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;void&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;WritableSignal&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;delegated&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;computation&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;delegated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;delegated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;updateFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&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;T&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;updateFn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;delegated&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;delegated&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="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;``&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;UserPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;street&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Main Street&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;London&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;userFormModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;delegatedSignal&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="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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;street&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
      &lt;span class="p"&gt;}&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;user&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;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;street&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;street&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;street&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="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;userForm&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;userFormModel&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;delegatedSignal&lt;/code&gt; can be used for different use cases. Not just forms. Regarding the SignalStore, you could connect a Signal Form and a SignalStore together, where each change in the form is directly written to the SignalStore.&lt;/p&gt;

&lt;p&gt;You can see the &lt;code&gt;delegatedSignal&lt;/code&gt; as a &lt;code&gt;linkedSignal&lt;/code&gt; which doesn't create a clone, but just writes directly back to the original Signal. &lt;code&gt;delegatedSignal&lt;/code&gt; exists already in the Angular framework (slightly differently as &lt;code&gt;deepSignal&lt;/code&gt;), but is not exposed publicly. Angular uses it for the Signal Forms:&lt;br&gt;
&lt;a href="https://github.com/angular/angular/blob/394ad0c2a26eec8a8f7136b1b7971420b30a117e/packages/forms/signals/src/util/deep_signal.ts#L21" rel="noopener noreferrer"&gt;https://github.com/angular/angular/blob/394ad0c2a26eec8a8f7136b1b7971420b30a117e/packages/forms/signals/src/util/deep_signal.ts#L21&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ngrx/platform/issues/5121" rel="noopener noreferrer"&gt;ngrx/platform#5121 — RFC delegatedSignal&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Resource Extensions
&lt;/h3&gt;

&lt;p&gt;And the second RFC is related to resources. It allows to extend the resources which goes beyond the possibilities of the current &lt;code&gt;snapshot&lt;/code&gt; function. For example, an extension would change the behavior of a resource in an error state, where an access to the value does not throw. Custom extensions are possible as well and there is even the option to define default extensions.&lt;/p&gt;

&lt;p&gt;All two issues were created by &lt;a class="mentioned-user" href="https://dev.to/markostanimirovic"&gt;@markostanimirovic&lt;/a&gt; and if the same Marko was also guest at a previous episode of the Angular Plus show. So if you are interested to hear more about state management and SignalStore specifically, you should check out the episode.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ngrx/platform/issues/5126" rel="noopener noreferrer"&gt;ngrx/platform#5126 — RFC resource extensions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/hBOwrpnUDds"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h2&gt;
  
  
  Martina Kraus on security (Angular Plus Show)
&lt;/h2&gt;

&lt;p&gt;In other news, the Angular Plus Show also had Martina Kraus as guest, which usually means the topic is about security.&lt;/p&gt;

&lt;p&gt;Together with the three hosts, Lara Newsom, Brooke Avery, and Jan-Niklas Wortmann, they discussed a whole portfolio of security. Be it trusted types, Sanitization, attacks like XSS and CSRF, but also content policies and the increased risk that comes with AI.&lt;/p&gt;

&lt;p&gt;At the end, Martina gave some tips where to start with security and she also highlighted the OWASP juice shop, which is written in Angular and is a playground to try out different vulnerabilities.&lt;/p&gt;

&lt;p&gt;And by the way, you should not store your access token in local storage.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/kyxF0Kk3WEQ"&gt;
  &lt;/iframe&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://owasp.org/www-project-juice-shop/" 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%2Fowasp.org%2Fwww--site-theme%2Ffavicon.ico" height="64" class="m-0" width="64"&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://owasp.org/www-project-juice-shop/" rel="noopener noreferrer" class="c-link"&gt;
            OWASP Juice Shop | OWASP Foundation
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Probably the most modern and sophisticated insecure web application for security trainings, awareness demos and CTFs. Also great voluntary guinea pig for your security tools and DevSecOps pipelines!
          &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%2Fowasp.org%2Fwww--site-theme%2Ffavicon.ico" width="64" height="64"&gt;
          owasp.org
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Form validation: debouncing async validators
&lt;/h2&gt;

&lt;p&gt;And we have a third debounce option in Angular. For Signal Forms, there is a &lt;code&gt;debounce&lt;/code&gt; function, which debounces the synchronization of a form field with the underlying model. The second is a &lt;code&gt;debounced&lt;/code&gt; function, scheduled for Angular 22 and is meant for any Signal type out there. The new one, is debouncing for asynchronous validators in Signal Forms. That allows you to have "undebounced" synchronous validators, but debouncing an asynchronous validator.&lt;/p&gt;

&lt;p&gt;That feature has been merged into the 22 version branch, but didn't make it into the latest 21.2.7 version. So it seems, we have to wait for Angular 22.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/commit/24e52d450d201e3da90bb64f84358f9eccd7877d" rel="noopener noreferrer"&gt;angular/angular@24e52d4 — debounce on validateAsync / validateHttp&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Alfredo Perez: SpecKit and SpecKit Companion
&lt;/h2&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/alfredoperez"&gt;@alfredoperez&lt;/a&gt; published a three-article series about a Spec-driven development process with AI. The most prominent tool in that spectrum is GitHub's SpecKit, which Alfredo describes. Additionally, he has created a VSCode extension, called SpecKit Companion, not just to visualize but also to edit and execute that specification.&lt;/p&gt;

&lt;p&gt;Since GitHub's SpecKit is not the only tool out there, Alfredo also shows alternatives and how SpecKit Companion can be configured to support those tools as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/ngconf/speckit-companion-e4fc99d1e061" rel="noopener noreferrer"&gt;https://medium.com/ngconf/speckit-companion-e4fc99d1e061&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/ngconf/custom-workflows-in-speckit-companion-266fda3b5eec" rel="noopener noreferrer"&gt;https://medium.com/ngconf/custom-workflows-in-speckit-companion-266fda3b5eec&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/ngconf/build-your-own-sdd-workflow-daa3fc1ae673" rel="noopener noreferrer"&gt;https://medium.com/ngconf/build-your-own-sdd-workflow-daa3fc1ae673&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Graz Meetup videos
&lt;/h2&gt;

&lt;p&gt;Finally, the recordings of the Angular Graz Meetup are available on YouTube. They are published not at once but in a regular interval.&lt;/p&gt;

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

</description>
      <category>angular</category>
      <category>ngrx</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Ng-News 26/10: Signality, Vitest 4.1, Angular Skills</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Fri, 27 Mar 2026 18:56:51 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2610-signality-vitest-41-angular-skills-19m3</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2610-signality-vitest-41-angular-skills-19m3</guid>
      <description>&lt;p&gt;This week's ng-news covers ngxtension on Angular Space, Signality's signal-first utilities inspired by VueUse, and Vitest 4.1 fake-timer improvements for Angular tests. We also look at official Angular agent skills.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Angular Space and ngxtension
&lt;/h2&gt;

&lt;p&gt;ngxtension, a set of utility functions, was the topic on the Angular Space live stream. The hosts were - as always - Armen Vardanyan and Enea Jahollari, the maintainer of ngxtension; Enea joined the stream after a few minutes.&lt;/p&gt;

&lt;p&gt;They discussed several main features. For example, &lt;code&gt;injectParams&lt;/code&gt;, which a former episode of ng-news covered already, and the &lt;code&gt;on&lt;/code&gt; helper, which offers strong developer experience for explicit effects but can also be used for explicit signal tracking in &lt;code&gt;computed&lt;/code&gt;, resources, or &lt;code&gt;linkedSignal&lt;/code&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://ngxtension.dev/" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;ngxtension.dev&lt;/span&gt;
          

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


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

&lt;h2&gt;
  
  
  Signality
&lt;/h2&gt;

&lt;p&gt;Another promising library that offers utility functions - this time only signal-based - was published. Signality is its name, and according to its author, Vyacheslav Borodin, it is heavily inspired by VueUse, a popular library of utilities for Vue.js. Although Signality was released at version 0.1, the number of functions is already quite impressive.&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://signality.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%2Fsignality.dev%2Fog-image.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://signality.dev/" rel="noopener noreferrer" class="c-link"&gt;
            Getting started | Signality
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Comprehensive library of signal-first utilities for Angular. SSR-ready, type-safe, and designed for seamless reactive composition and DI-interop.
          &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%2Fsignality.dev%2Ffavicon-32x32.png" width="32" height="32"&gt;
          signality.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Vitest 4.1 fake timers
&lt;/h2&gt;

&lt;p&gt;Vitest, Angular's default testing framework for new projects, was released in version 4.1 and gained a major improvement in handling asynchronous timers. Fake timers gained an automatic tick mode.&lt;/p&gt;

&lt;p&gt;In the past, when code used a delayed timer - for example because of &lt;code&gt;debounceTime&lt;/code&gt; - you often had to advance those timers manually in tests. Now there is a mode that advances scheduled timers asynchronously without you hard-coding each delay. You no longer need to remember whether it was 100 ms, 200 ms, or something else. It does not remove asynchronicity, but it runs the deferred work on a short tick - roughly speaking, along the lines of &lt;code&gt;setTimeout(() =&amp;gt; void true, 0)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/younesjd"&gt;@younesjd&lt;/a&gt; added a section about that feature to his cookbook, and the Vitest documentation has more detail.&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://main.vitest.dev/api/vi.html#vi-settimertickmode" 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%2Fvitest.dev%2Fog.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://main.vitest.dev/api/vi.html#vi-settimertickmode" rel="noopener noreferrer" class="c-link"&gt;
            Vi | Vitest
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Next generation testing framework powered by Vite
          &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%2Fmain.vitest.dev%2Ffavicon.ico" width="64" height="64"&gt;
          main.vitest.dev
        &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://cookbook.marmicode.io/angular/testing/controlling-time-in-tests#fake-timers-in-fast-forward-mode" 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%2Fcookbook.marmicode.io%2Fimg%2Fsocial-card.png" height="418" 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://cookbook.marmicode.io/angular/testing/controlling-time-in-tests#fake-timers-in-fast-forward-mode" rel="noopener noreferrer" class="c-link"&gt;
            Controlling Time in Tests | Marmicode Cookbook
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Understand why time-based behavior is challenging to test and how fake timers and dynamic timing configuration address different scenarios.
          &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%2Fcookbook.marmicode.io%2Fimg%2Ffavicon.png" width="64" height="64"&gt;
          cookbook.marmicode.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Official Angular agent skills
&lt;/h2&gt;

&lt;p&gt;Official Angular skills have landed. You can install them now with &lt;code&gt;npx skills add angular/skills&lt;/code&gt;. After that, your agent should pick them up whenever the LLM decides to use them.&lt;/p&gt;

&lt;p&gt;Skills are text content that explains to the LLM - for example, how Signal Forms work or how Angular's dependency injection works. The main distinction from MCP servers, basic rules, custom instructions, or whatever term your agent uses, is that skills are not loaded automatically up front. A skill starts with a short description of what it covers, which does not overload context, and - as noted above - when the LLM decides it is time to use one, it can load the full body on demand.&lt;/p&gt;

&lt;p&gt;That pattern lets you keep many skills available without bloating every prompt.&lt;/p&gt;

&lt;p&gt;Angular skills are not new. Ng-News already covered the Analog.js skills, which were created in January. As their author Brandon Roberts confirmed, now that official Angular skills exist, the Analog.js skills are deprecated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/skills" rel="noopener noreferrer"&gt;angular/skills (GitHub)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2036184874898321635-415" src="https://platform.twitter.com/embed/Tweet.html?id=2036184874898321635"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2036184874898321635-415');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2036184874898321635&amp;amp;theme=dark"
  }



&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>vitest</category>
      <category>ai</category>
    </item>
    <item>
      <title>Ng-News 26/09: AI &amp; Angular, debounced() in v22, Oxidation Compiler in Analog</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Thu, 19 Mar 2026 20:43:38 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2609-ai-angular-debounced-in-v22-oxidation-compiler-in-analog-4n3</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2609-ai-angular-debounced-in-v22-oxidation-compiler-in-analog-4n3</guid>
      <description>&lt;p&gt;Ng-News 26-09 features three topics: the new Signal-based &lt;code&gt;debounced&lt;/code&gt; API,  the Oxidation compiler benchmark in Analog.js, and AI &amp;amp; Angular.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular XSS Advisory
&lt;/h2&gt;

&lt;p&gt;A Cross-Site Scripting (XSS) vulnerability was discovered in Angular. If you use Angular i18n and apply it to HTML attributes, their values are not sanitized. The fix was applied to the supported versions Angular 19, 20, and 21.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/security/advisories/GHSA-g93w-mfhg-p222" rel="noopener noreferrer"&gt;Angular security advisory (GitHub)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ng-Asia with Mark Thompson
&lt;/h2&gt;

&lt;p&gt;Mark Thompson, Angular DevRel, was guest at Ng-Asia hosted by Ilyoskhuja Ikromkhujaev. The session was a mix between presentation and Q&amp;amp;A.&lt;/p&gt;

&lt;p&gt;For example, Mark presented his view on how AI will shape the way development will work for us. He doesn't expect a replacement a software developers, but - as many people would agree - a shift in terms of activities/competencies.&lt;/p&gt;

&lt;p&gt;He also explained what AI means for future applications, where the UI is highly responsive and can be seen as just another AI tool, instrumented by an LLM. There are libraries that support that use case already, like HashBrown.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Q&amp;amp;A with Mark Thompson
&lt;/h2&gt;

&lt;p&gt;Mark Thompson also hosted the monthly Angular Q&amp;amp;A session. His guest was Alan from the Angular team and the main topic was AI - specifically Angular's MCP server combined with Chrome's MCP server. MCP allows LLMs to perform actions, not just return text. Angular's MCP server provides up-to-date documentation on best practices, can help migrate to zoneless, or act as a tutor. Together with Chrome's MCP server, it allows the LLM to verify its generated code automatically and fix it.&lt;/p&gt;

&lt;p&gt;Two answers stood out. First, a nice analogy on how skills and MCP tools differentiate. According to Mark, a tool's execution is more deterministic, whereas a skill is still text, which needs to be processed by the LLM, and could therefore cause non-deterministic, but better or different results, than an MCP tool's author could achieve.&lt;/p&gt;

&lt;p&gt;He compared it with playing a piece of music on a guitar. In the case of an MCP tool and if the LLM would be an artist, then the LLM would play a piece always in the same way - without even knowing how or what it is doing.&lt;br&gt;
In the context of a skill, it would learn how to play the guitar and could probably identify certain things that the tool would have oversawn.&lt;br&gt;
For example Mark mentioned, that there could a first part of a piece, which the tool was not aware of, but the skill would cover it.&lt;/p&gt;

&lt;p&gt;Second, why is Angular investing so much in AI? According to Mark, if you have a framework without AI support, many developers will say that it is not ready for the future and will switch to others. Given AI's omnipresence, having an AI-ready framework is a reasonable choice. &lt;/p&gt;

&lt;p&gt;Timestamp 41:20.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Oxidation Compiler and Analog
&lt;/h2&gt;

&lt;p&gt;As mentioned in a previous episode, there is an experimental Angular compiler, which is developed by Void Zero and is called the Oxidation compiler (Oxc).&lt;br&gt;
The interesting thing is that it is written in Rust, and not in Go, which is the language of choice for the upcoming official TypeScript rewrite.&lt;/p&gt;

&lt;p&gt;Brandon Roberts, who is well known in the Angular community, has integrated the Oxidation compiler into Analog.js, the most popular meta-framework for Angular, which supports building Angular with Vite. Brandon posted a benchmark stating that build time with Angular's esbuild dropped from 47 seconds to 1.5 seconds - a roughly 97% improvement.&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2029653775330292103-98" src="https://platform.twitter.com/embed/Tweet.html?id=2029653775330292103"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2029653775330292103-98');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2029653775330292103&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Roadmap Update
&lt;/h2&gt;

&lt;p&gt;Angular's roadmap got a major update, or one could say a reprioritization. In short, AI is king: topics like a new authoring format, streaming for server-side rendering, or improvements to the &lt;code&gt;TestBed&lt;/code&gt; were removed. That does not mean these topics will never be worked on, but they are deprioritized for now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/commit/53c1a1cee70753fc61fe0f7e115929e653fd5b82" rel="noopener noreferrer"&gt;Angular roadmap change (GitHub commit)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular NPM Downloads
&lt;/h2&gt;

&lt;p&gt;If you are a fan of download numbers: despite the results of the State of JavaScript survey, Angular appears to be in a strong position. In May 2025, weekly downloads exceeded 4 million for the first time. In the week of March 9th they were above 5 million - roughly a 25% increase within a year. For reference, Angular passed 3 million weekly downloads in February 2022.&lt;/p&gt;

&lt;p&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://npmtrends.com/@angular/core" 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%2Fnpmtrends.com%2Fimages%2Fnpm_trends_share_image.png" height="auto" class="m-0"&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://npmtrends.com/@angular/core" rel="noopener noreferrer" class="c-link"&gt;
            @angular/core | npm trends
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Comparing trends for @angular/core 21.2.6 which has 5,338,072 weekly downloads and 100,138 GitHub stars.
          &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%2Fnpmtrends.com%2Ffavicon.ico"&gt;
          npmtrends.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;h2&gt;
  
  
  Debounced API
&lt;/h2&gt;

&lt;p&gt;Fatima Amzil published an article about a new Signal-based function called &lt;code&gt;debounced&lt;/code&gt;. Do not confuse it with the &lt;code&gt;debounce&lt;/code&gt; function in Signal Forms: that one is limited to Signal Forms and debounces the synchronization of a form field with the underlying model. The new &lt;code&gt;debounced&lt;/code&gt; is meant for any Signal - you can use it to debounce a resource's value, a computed, a linkedSignal, or a function that returns a value (which will be automatically tracked). The return value is not another Signal but a resource. &lt;code&gt;debounced&lt;/code&gt; is targeted for Angular 22.&lt;/p&gt;

&lt;p&gt;Michael Small also contributed a post on Bluesky with a GIF demonstrating the new function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://famzil.medium.com/angular-22-the-power-of-debound-and-debounced-apis-c41e33c0a18e" rel="noopener noreferrer"&gt;https://famzil.medium.com/angular-22-the-power-of-debound-and-debounced-apis-c41e33c0a18e&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;blockquote class="bluesky-embed"&gt;
&lt;p&gt;Just landed in the Angular nightly: debouncing signals. 

Photo of code snippet + link to PR in this thread

github.com/angular/angu...&lt;/p&gt;— &lt;a href="https://bsky.app/profile/did:plc:3jf7btbezgqcaxpdoru7zr2l?ref_src=embed" rel="noopener noreferrer"&gt;Michael Small (@michaelsmalldev.bsky.social)&lt;/a&gt; &lt;a href="https://bsky.app/profile/did:plc:3jf7btbezgqcaxpdoru7zr2l/post/3mgnuxoqkes2d?ref_src=embed" rel="noopener noreferrer"&gt;2026-03-09T22:14:51.079Z&lt;/a&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Angular Vienna and Code Magazine
&lt;/h2&gt;

&lt;p&gt;In other news, the Angular Vienna meetup took place and the recording of the live stream is available on YouTube. At the meetup, Dmytro Mezhenskyi from Decoded Frontends gave his first public talk. Other speakers were Matthieu Riegler from the Angular team on JavaScript in general and the upcoming changes in Angular due to the TypeScript rewrite in Go, Manfred Steyer on AI in Angular, and Daniel Szendrei on Angular hacks.&lt;/p&gt;

&lt;p&gt;Sonu Kapoor published an in-depth article on the evolution of Angular forms in Code Magazine. The article contains almost 15,000 words.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;p&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://www.codemag.com/Article/264041/From-Template-Driven-to-Signal-Driven-The-Complete-Evolution-of-Angular-Forms" 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%2Fepsenterprise.blob.core.windows.net%2Fpermanent-files%2FFileAttachments%2Fe4008125_f5eb_45f2_8d9d_4302f88043b6%2F264041_Header_Rectangle.jpeg" height="auto" class="m-0"&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.codemag.com/Article/264041/From-Template-Driven-to-Signal-Driven-The-Complete-Evolution-of-Angular-Forms" rel="noopener noreferrer" class="c-link"&gt;
            From Template-Driven to Signal-Driven: The Complete Evolution of Angular Forms
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Sonu Kapoor's article, "From Template-Driven to Signal-Driven: The Complete Evolution of Angular Forms," provides a comprehensive exploration of Angular's evolving form APIs, tracing their journey ...
          &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%2Fwww.codemag.com%2Fimages%2FCodeIcon.png"&gt;
          codemag.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>webdev</category>
      <category>angular</category>
      <category>frontend</category>
      <category>ai</category>
    </item>
    <item>
      <title>Ng-News 26/08: Angular 21.2</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Thu, 12 Mar 2026 17:54:46 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2608-angular-212-223j</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2608-angular-212-223j</guid>
      <description>&lt;p&gt;The release of Angular 21.2 introduced several significant features - most notably for Signal Forms - while also delivering key enhancements across the broader framework.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt;Angular 21.2 was released. According to the plan, that was the last minor release in the 21.x series. The next major release will be Angular 22 in May. According to schematic versioning, a minor brings only bug fixes and small features, but there is quite a lot in this release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signal Forms
&lt;/h2&gt;

&lt;p&gt;Signal Forms have picked up several useful features that round it out and suggest it is moving toward stability or developer preview.&lt;/p&gt;

&lt;h3&gt;
  
  
  Form Submission
&lt;/h3&gt;

&lt;p&gt;For example, the need to manually disable form submission is now handled in a simple way. You no longer have to wire this yourself: add the &lt;code&gt;formRoot&lt;/code&gt; directive to the form and it turns off the browser default submit behavior (e.g. full page reload).&lt;/p&gt;

&lt;p&gt;You configure the submit handler via the &lt;code&gt;submission&lt;/code&gt; option of the &lt;code&gt;form()&lt;/code&gt; function. That handler runs only when the user actually submits (e.g. Enter or the submit button) and when the form is not invalid.&lt;/p&gt;

&lt;p&gt;By default, that means submit can run even while asynchronous validators are still pending.&lt;/p&gt;

&lt;p&gt;While an async validator is running, it keeps &lt;code&gt;{invalid: false, valid: false}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Submit only happens if the &lt;code&gt;invalid&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, so pending validators do not block submission.&lt;/p&gt;

&lt;p&gt;You can change this with &lt;code&gt;ignoreValidators: 'none'&lt;/code&gt; if you want to wait until all validators, including async, have finished.&lt;/p&gt;

&lt;p&gt;The default is permissive because the server will validate again on submit anyway, so there is no need to wait for client-side async validators before allowing the request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Injectable&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;FormRoot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;validateAsync&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;validateStandardSchema&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/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;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;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="nx"&gt;FormRoot&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;form [formRoot]="userForm"&amp;gt;
      &amp;lt;input [formField]="userForm.firstName" /&amp;gt;
      &amp;lt;input [formField]="userForm.lastName" /&amp;gt;
    &amp;lt;/form&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;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;userForm&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;submission&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&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;user&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;protected&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;userService&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;UserService&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://stackblitz.com/edit/github-xuyek34y?file=src%2Fmain.ts" rel="noopener noreferrer"&gt;Code Example on Stackblitz&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Custom Control
&lt;/h3&gt;

&lt;p&gt;For custom controls, we now have the ability to use the &lt;code&gt;transformedValue&lt;/code&gt; utility for formatting and parsing.&lt;/p&gt;

&lt;p&gt;For example, it can be used for input fields with non-English number or date formats.&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;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;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;FormRoot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FormValueControl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;transformedValue&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/forms/signals&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;JsonPipe&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common&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-german-number-field&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;&amp;lt;ng-content /&amp;gt;&amp;lt;/p&amp;gt;
      &amp;lt;input
        matInput
        [value]="rawValue()"
        (input)="rawValue.set($event.target.value)"
      /&amp;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="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;GermanNumberField&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;FormValueControl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&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;readonly&lt;/span&gt; &lt;span class="nx"&gt;rawValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;transformedValue&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;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;format&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="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&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;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="nx"&gt;FormRoot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GermanNumberField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JsonPipe&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;form [formRoot]="userForm"&amp;gt;
    &amp;lt;app-german-number-field [formField]="userForm.heightInMeter"&amp;gt;Height in Meters&amp;lt;/app-german-number-field&amp;gt;
    {{user() | json}}
    &amp;lt;/form&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;heightInMeter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.75&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;userForm&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;user&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://stackblitz.com/edit/github-xuyek34y-fdnj2dgg?file=src%2Fmain.ts" rel="noopener noreferrer"&gt;Code Example on Stackblitz&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  SignalFormControl
&lt;/h3&gt;

&lt;p&gt;Although the improved form submission and the advanced features for custom controls are really great, most of us work with an existing Angular application.&lt;/p&gt;

&lt;p&gt;For us, the most important new feature is &lt;code&gt;SignalFormControl&lt;/code&gt;. It allows you to introduce a &lt;code&gt;FormControl&lt;/code&gt; into Reactive Forms that supports, for example, the advanced validation rules from Signal Forms.&lt;/p&gt;

&lt;p&gt;That makes the migration to Signal Forms much easier.&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;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="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;required&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validateAsync&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SignalFormControl&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/compat&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;FormBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactiveFormsModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/forms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="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;ReactiveFormsModule&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;form [formGroup]="userForm"&amp;gt;
      &amp;lt;input formControlName="email" /&amp;gt;
    &amp;lt;/form&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;userForm&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;FormBuilder&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;nonNullable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SignalFormControl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@host.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;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="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email is reqired&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nf"&gt;debounce&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="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;validateAsync&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="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="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="nx"&gt;ctx&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="na"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&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;return&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="nx"&gt;params&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&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="na"&gt;onSuccess&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;networkError&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://stackblitz.com/edit/github-xuyek34y-hwaqwg2v?file=src%2Fmain.ts" rel="noopener noreferrer"&gt;Code Example on Stackblitz&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;ResourceSnapshot&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The Resource Snapshot API was finally released. That is a feature that was expected to land in Angular 21 already; it was in the main branch but got reverted.&lt;/p&gt;

&lt;p&gt;In short, Resource Snapshots allow you to map one resource to another or use them for compositional tasks.&lt;/p&gt;

&lt;p&gt;The example given in the docs changes the default behavior of setting the value to undefined during loading to keeping the original value. In Angular's codebase, the snapshot is used for testing, where it acts as a convenient resource factory function. We will see what use cases are possible.&lt;/p&gt;

&lt;p&gt;The example below shows an error handler, which can be used to avoid the &lt;code&gt;error&lt;/code&gt; status.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;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="nx"&gt;resourceFromSnapshots&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;JsonPipe&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common&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;FormField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FormRoot&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="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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;withErrorHandler&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="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;errorHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&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;T&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;snap&lt;/span&gt; &lt;span class="o"&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;snapshot&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;snap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&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;try&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resolved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;as&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;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;errorHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;as&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;error&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;snap&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;resourceFromSnapshots&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="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;FormRoot&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;JsonPipe&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;form [formRoot]="idForm"&amp;gt;
      &amp;lt;input [formField]="idForm.id" type="number"/&amp;gt;

      &amp;lt;pre&amp;gt;{{safeUser.value() | json}}&amp;lt;/pre&amp;gt;
      &amp;lt;pre&amp;gt;{{unsafeUser.value() | json}}&amp;lt;/pre&amp;gt;
    &amp;lt;/form&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="nx"&gt;idForm&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="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

  &lt;span class="nx"&gt;unsafeUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;idForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;value&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;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="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;no negative users ;)&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&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="nx"&gt;safeUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;withErrorHandler&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;unsafeUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Undefined&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://stackblitz.com/edit/github-xuyek34y-ijamx4nz?file=src%2Fmain.ts" rel="noopener noreferrer"&gt;Code Example on Stackblitz&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  CLI - Prettier Integration
&lt;/h2&gt;

&lt;p&gt;As the CLI already provides full integration of Tailwind CSS, Angular 21 also integrates Prettier as a first-class citizen.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lambdas in Templates
&lt;/h2&gt;

&lt;p&gt;The syntax in the template, which is not native JavaScript, has been extended with two new features. We can now use lambda functions directly in templates.&lt;/p&gt;

&lt;p&gt;The favored use case is to call the update method on a signal.&lt;/p&gt;

&lt;p&gt;In general, logic should stay out of the template, so do not overuse this feature.&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;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-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;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
  &amp;lt;p&amp;gt;Current Value: {{counter()}}&amp;lt;/p&amp;gt;
  &amp;lt;button (click)="counter.update((value) =&amp;gt; value + 1)"&amp;gt;Increment&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;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;counter&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://stackblitz.com/edit/github-xuyek34y-fcuywgfs?file=src%2Fmain.ts" rel="noopener noreferrer"&gt;Code Example on Stackblitz&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Exhaustive Checks
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;@switch&lt;/code&gt; statement now supports exhaustive checking: the compiler verifies that all possible cases are covered when you use &lt;code&gt;@default never&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;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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anonymous&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;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
@switch(userType) {
  @case('anonymous') {
    &amp;lt;p&amp;gt;Welcome Visitor&amp;lt;/p&amp;gt;
  }
  @case('admin') {
    &amp;lt;p&amp;gt;Welcome admin&amp;lt;/p&amp;gt;
  }
  @default never;
}

  `&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="nl"&gt;userType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://stackblitz.com/edit/github-xuyek34y-w7z7amxv?file=src%2Fmain.ts" rel="noopener noreferrer"&gt;Code Example on Stackblitz&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ChangeDetectionStrategy.Eager
&lt;/h2&gt;

&lt;p&gt;As already announced, &lt;code&gt;ChangeDetectionStrategy.Default&lt;/code&gt; was renamed to &lt;code&gt;ChangeDetectionStrategy.Eager&lt;/code&gt;. The reason is that in Angular 22, in May, the default will become &lt;code&gt;OnPush&lt;/code&gt;, and because it does not make sense to call the non-default option "default", its new name is Eager.&lt;/p&gt;

&lt;p&gt;You do not have to change anything. If you explicitly use &lt;code&gt;ChangeDetectionStrategy.Default&lt;/code&gt;, you can remove that setting or, even better, migrate to &lt;code&gt;OnPush&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You are not forced to change anything. When Angular 22 is released, the update scripts will explicitly set existing implicit or explicit components with &lt;code&gt;ChangeDetectionStrategy.Default&lt;/code&gt; to &lt;code&gt;ChangeDetectionStrategy.Eager&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Sources and Thanks
&lt;/h2&gt;

&lt;p&gt;For further information, check out the official changelog and a big thanks to Cedric Exbrayat&lt;/p&gt;

&lt;p&gt;His article was the main source for this episode.&lt;/p&gt;

&lt;p&gt;Merci beaucoup Cedric!&lt;/p&gt;

&lt;p&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://blog.ninja-squad.com/2026/02/26/what-is-new-angular-21.2" 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%2Flogo.svg" height="auto" class="m-0"&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/02/26/what-is-new-angular-21.2" rel="noopener noreferrer" class="c-link"&gt;
            What's new in Angular 21.2? - Ninja Squad
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Angular 21.2 is out!
          &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"&gt;
          blog.ninja-squad.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;&lt;a href="https://github.com/angular/angular/blob/main/CHANGELOG.md" rel="noopener noreferrer"&gt;Angular CHANGELOG (GitHub)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Ng-News 26/07: Angular's Router, Vitest, Hashbrown, History &amp; Popularity</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Tue, 24 Feb 2026 23:24:05 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2607-angulars-router-vitest-hashbrown-history-popularity-4phc</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2607-angulars-router-vitest-hashbrown-history-popularity-4phc</guid>
      <description>&lt;p&gt;Andrew Scott on Angular's Router, Vitest with Younes Jaadi, Hashbrown and AI, State of JS and 100k stars, Maximilian's Angular retrospective, ngxtension 7.1 and ngDiagram 1.0.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Andrew Scott on Angular's Router
&lt;/h2&gt;

&lt;p&gt;Andrew Scott, member of the Angular team, was a guest on Armen Vardanyan's podcast at Angular Space, and they discussed a wide range of topics.&lt;/p&gt;

&lt;p&gt;They talked about a potential integration of resources into the router, where the router would know exactly what kind of data needs to be loaded and the loading could also be done in parallel. Right now we have a waterfall effect, where each segment with its resolvers needs to be loaded sequentially.&lt;/p&gt;

&lt;p&gt;On RxJS, it is still going to become optional in the future, but that does not have the highest priority at the moment.&lt;/p&gt;

&lt;p&gt;Another topic was the relationship between community libraries and Angular. For example, ngxtension has a lot of useful utility functions for the router, which would make sense to be part of the framework. Andrew meant that the framework should provide the building blocks and the community should build certain features on top of it.&lt;/p&gt;

&lt;p&gt;The TypeScript rewrite in Go was also discussed. A lot of the Angular team's time is currently going into preparing for that rewrite.&lt;/p&gt;

&lt;p&gt;Theoretically, a mixed approach might also be possible. Alex Rickabaugh, lead of the Angular framework, was not on the podcast, but he posted that they are looking into using Rust in some parts of Angular's compilation process.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2024164838688379157-601" src="https://platform.twitter.com/embed/Tweet.html?id=2024164838688379157"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2024164838688379157-601');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2024164838688379157&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;h2&gt;
  
  
  Younes Jaadi on Vitest
&lt;/h2&gt;

&lt;p&gt;Younes Jaadi posted a video about Vitest, which is Angular's default testing framework since Angular version 21.&lt;/p&gt;

&lt;p&gt;His main focus was on the so-called browser mode, which uses an E2E-style runner such as Playwright or WebdriverIO to interact with the DOM. He shared technical insights and pragmatic tips on how to use Vitest.&lt;/p&gt;

&lt;p&gt;Younes is highly respected in the Angular community and has been promoting Vitest in Angular before it became the official testing framework.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Manfred Steyer on Hashbrown and AI in Angular
&lt;/h2&gt;

&lt;p&gt;AI shows up in many places, including Angular, where it can generate dynamic components, accept prompts, and call tools on the fly. A prominent library for this is Hashbrown.&lt;/p&gt;

&lt;p&gt;Manfred Steyer has written a three-article series on the topic: basic setup, integrating a prompt, connecting with your application, and more advanced features such as dynamic components or letting Hashbrown execute code in the browser.&lt;/p&gt;

&lt;p&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://www.angulararchitects.io/en/blog/dynamic-reports-natural-lanaguage-queries-with-on-the-fly-code-generation/" 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%2F02%2Fsujet-2-1024x536.png" height="auto" class="m-0"&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/dynamic-reports-natural-lanaguage-queries-with-on-the-fly-code-generation/" rel="noopener noreferrer" class="c-link"&gt;
            Dynamic Reports: Natural Language Queries with On-the-Fly Code Generation - 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"&gt;
          angulararchitects.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;h2&gt;
  
  
  State of JavaScript and Angular's popularity
&lt;/h2&gt;

&lt;p&gt;State of JavaScript released the results from last year. Angular saw a rise in 2024 in metrics around popularity and satisfaction, and a small decline in 2025, with some gap to 2023. The survey's sample is often said to be not representative, so the numbers may not reflect the broader population.&lt;/p&gt;

&lt;p&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"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://stateofjs.com/en-US" rel="noopener noreferrer" class="c-link"&gt;
            State of JavaScript
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
          stateofjs.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;Angular's repository on GitHub has reached 100,000 stars. For comparison, React has about 240,000 and Vue about 53,000. Enea Jahollari posted about a Reddit thread on the webdev subreddit where someone asked if Angular is still used; as Enea put it, there were some good comments about Angular.&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2024897592006422590-594" src="https://platform.twitter.com/embed/Tweet.html?id=2024897592006422590"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2024897592006422590-594');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2024897592006422590&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;h2&gt;
  
  
  Maximilian Schwarzmüller – 10 Years of Angular
&lt;/h2&gt;

&lt;p&gt;Maximilian Schwarzmüller is a well-known name in Angular. His Udemy course has been the door opener for many Angular developers since 2016. He published a video titled "Looking back at 10 years of Angular - and into its future", covering the early days, milestones, and where we are now. If you want nostalgia or a brief overview of Angular's history, it's a good watch.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Also in the News
&lt;/h2&gt;

&lt;p&gt;Ngxtension 7.1 brought &lt;code&gt;injectParams.global()&lt;/code&gt;, which gives you one signal with all the parameters of the current route hierarchy.&lt;/p&gt;

&lt;p&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://ngxtension.dev/" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;ngxtension.dev&lt;/span&gt;
          

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




&lt;p&gt;ngDiagram had its first stable release with version 1. It has zero dependencies, is based on modern Angular, and lets you create interactive diagrams. It looks very promising.&lt;/p&gt;

&lt;p&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://www.ngdiagram.dev/" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;ngdiagram.dev&lt;/span&gt;
          

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




&lt;p&gt;If you use VS Code, check out the latest Angular VS Code extension; it includes some new goodies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/releases/tag/vsix-21.2.0/" rel="noopener noreferrer"&gt;https://github.com/angular/angular/releases/tag/vsix-21.2.0/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>angular</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Ng-News 26/05: OnPush as Default, Agent Skills, Q&amp;A</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Wed, 11 Feb 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2605-onpush-as-default-agent-skills-qa-glb</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2605-onpush-as-default-agent-skills-qa-glb</guid>
      <description>&lt;p&gt;Agent Skills are landing for Angular. This episode also covers the January Angular Q&amp;amp;A (Jeremy Elbourn leaving, markForCheck discussion, Dart's legacy) and Mark Thompson's RFC to make OnPush the default.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Skills landing in Analog first, and now in Angular
&lt;/h2&gt;

&lt;p&gt;The AI world continues to evolve, and things that were top notch yesterday are already outdated today. When it comes to teaching AI how to write proper and modern Angular code, the answer in 2025 was the Angular CLI's built-in MCP server. In 2026, the answer is Skills.&lt;/p&gt;

&lt;p&gt;With MCP, we have the issue that they overload the context size of the LLM, because the tools' manifest has to be loaded always. Skills, on the other hand, are lightweight. They are not loaded automatically - only a small amount of metadata. The whole content is only loaded once on demand, namely when the LLM decides that it is now time to use it.&lt;/p&gt;

&lt;p&gt;Skills, like MCP, were introduced by Anthropic, which stands behind Claude Code. They first introduced them in October last year and in December standardized them as Agent Skills. To use them, you usually need one of the common IDEs that are good at AI integration, and you are not limited to Claude's models; it also works with others like GPT or Gemini.&lt;/p&gt;

&lt;p&gt;Brandon Roberts posted that he added skills to Analog.js, which is a meta-framework for Angular. One week later, Angular reacted as well: Mark Thompson confirmed and created a PR so that Skills land officially in Angular.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2014895426088919431-979" src="https://platform.twitter.com/embed/Tweet.html?id=2014895426088919431"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2014895426088919431-979');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2014895426088919431&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;a href="https://github.com/angular/angular/pull/66834" rel="noopener noreferrer"&gt;Angular PR #66834&lt;/a&gt;&lt;br&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://claude.com/blog/equipping-agents-for-the-real-world-with-agent-skills" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;claude.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;br&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://agentskills.io/home" 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%2Fagent-skills.mintlify.app%2Fmintlify-assets%2F_next%2Fimage%3Furl%3D%252F_mintlify%252Fapi%252Fog%253Fdivision%253DDocumentation%2526title%253DOverview%2526description%253DA%252Bsimple%25252C%252Bopen%252Bformat%252Bfor%252Bgiving%252Bagents%252Bnew%252Bcapabilities%252Band%252Bexpertise.%2526primaryColor%253D%2525237f7f7f%2526lightColor%253D%252523bfbfbf%2526darkColor%253D%252523404040%2526backgroundLight%253D%252523ffffff%2526backgroundDark%253D%2525230d0d0f%26w%3D1200%26q%3D100" height="630" class="m-0" width="1200"&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://agentskills.io/home" rel="noopener noreferrer" class="c-link"&gt;
            Overview - Agent Skills
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A simple, open format for giving agents new capabilities and expertise.
          &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%2Fagentskills.io%2Fmintlify-assets%2F_mintlify%2Ffavicons%2Fagent-skills%2FxaP4f19bjp9SO_87%2F_generated%2Ffavicon%2Ffavicon-16x16.png" width="16" height="16"&gt;
          agentskills.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Angular Q&amp;amp;A with the Angular team
&lt;/h2&gt;

&lt;p&gt;We had the January Angular Q&amp;amp;A with the Angular team. As usual, Mark Thompson and Jeremy Elbourn were there, but this time they were joined by Doug Parker, the lead of the Angular CLI team. Unfortunately, it was also the last appearance of Jeremy Elbourn. He announced that he is leaving Google already in February. Jeremy Elbourn is the current Angular uber lead, which means he presides over the Angular projects - Material, framework, and the CLI. A successor has not been announced yet.&lt;/p&gt;

&lt;p&gt;A very interesting side note: Jeremy was discussing the behavior of markForCheck on event listeners. So at the moment, a handled DOM event triggers change detection, and there was an internal discussion about changing that. The outcome was not to do it now, but to integrate that change once the "legendary" Signal Components come out. Signal Components were announced as a requirement for zoneless and were planned to land in Angular 17. But in the end, zoneless could be done without those kinds of changes, and Signal Components lost in terms of priority.&lt;/p&gt;

&lt;p&gt;Using Dart in Angular had some negative consequences. It was there in the beginning but did not have the best impact on Angular's API. For example, Dart does not have types for DOM elements, and that's why &lt;code&gt;nativeElement&lt;/code&gt; is &lt;code&gt;any&lt;/code&gt;. Dart also does not have &lt;code&gt;undefined&lt;/code&gt;, and that's why &lt;code&gt;null&lt;/code&gt; shows up often in the older API.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  ChangeDetection OnPush should become the default for Angular
&lt;/h2&gt;

&lt;p&gt;Mark Thompson has published an RFC to set Angular's default change detection strategy to OnPush. The current one is called Default - probably not the best name.&lt;/p&gt;

&lt;p&gt;OnPush means that when Angular synchronizes the state of our application with the DOM, a component under OnPush has to be marked as dirty in order to be checked for actual change. That dirty marking only happens if you have a handled user event, run markForCheck manually, use the async pipe, or - of course - if a Signal changes. A component that is not dirty also excludes its children from the change detection process.&lt;/p&gt;

&lt;p&gt;Since Default is not the best name, it will get an alias called Eager, and that is already going to happen in Angular 21.2, which will be released later this month. The actual switch to OnPush as the default will happen in Angular 22.&lt;/p&gt;

&lt;p&gt;As always, existing codebases will not be modified - safety first. As it was when standalone became the default, existing apps will get the explicit setting to ChangeDetectionStrategy.Eager (aka Default) via automatic migration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/discussions/66779" rel="noopener noreferrer"&gt;RFC Discussion #66779&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>angular</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ng-News 26/04: Micro Frontends at Google</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Sun, 08 Feb 2026 23:38:00 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2604-micro-frontends-at-google-13ch</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2604-micro-frontends-at-google-13ch</guid>
      <description>&lt;p&gt;Doug Parker from the Angular team shared insights on Micro Frontends at Google — isolation, Protocol Buffers, and when to avoid the approach. This episode also covers the TypeScript Go rewrite progress, and Angular DevTools Signal Graph updates.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

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

&lt;p&gt;Doug Parker was a guest at the Angular Meetup Graz, which was this time more a podcast. Doug is a member of the Angular team, focuses on the CLI, and talked about Micro Frontends at Google.&lt;/p&gt;

&lt;p&gt;A little bit of context. Google has a monorepo, which means all applications are within one repository. That does not mean they use Micro Frontend architectures. In fact, there has been some information (also on ng-news) where we shared the Micro Frontend approach of Google's Cloud Console, which is based on a huge micro frontend architecture using an iFrame approach, which is not used anymore.&lt;/p&gt;

&lt;p&gt;Instead, the new concept is to do Micro Frontends in complete isolation. In order to avoid collisions with shared dependencies, Google plays it safe. They do not share anything at all. So a very autonomous solution. When it comes to shared logic, they use Protocol Buffers, where a service is not really shared between micro frontends but more a messaging infrastructure. Another requirement is that they have the need to combine multiple frameworks together.&lt;/p&gt;

&lt;p&gt;Doug's approach is to see Micro Frontends as a contract between apps. In the end, there is an interface that needs to be implemented and the infrastructure takes care of the integration.&lt;/p&gt;

&lt;p&gt;There are no plans to open source the solution once it is finished.&lt;/p&gt;

&lt;p&gt;When should Micro Frontends be used? Whenever the underlying problem could be solved in a different way, then try out that approach before Micro Frontends. For example build times could be improved in different ways.&lt;/p&gt;

&lt;p&gt;If there are hard UX requirements, a micro-frontend approach might be hard to implement.&lt;/p&gt;

&lt;p&gt;Lastly, very often Micro Frontends are used to reduce the communication between teams. One has to ask first, if this is actually the goal, or if the opposite approach, namely, where people need to talk with each other more, should be achieved.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Status Update on Go Rewrite of TypeScript
&lt;/h2&gt;

&lt;p&gt;Last year, TypeScript announced that they are going to rewrite the compiler in Go, which should bring performance improvements that might be an order of magnitude, so about 10 times.&lt;/p&gt;

&lt;p&gt;This undertaking takes some time and consumes obviously all the resources of the team. Push-based posted about the current state. We are coming closer and the upcoming version of TypeScript 6.0 will be the last one written in TypeScript.&lt;/p&gt;

&lt;p&gt;The Angular team follows and has already started to make their codebase ready for v6 as well.&lt;/p&gt;

&lt;p&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://www.linkedin.com/posts/push-based_angular-typescript-js-activity-7417946368138358784-yhU6/" 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%2Fmedia.licdn.com%2Fdms%2Fimage%2Fv2%2FD4D10AQGVLDyDhY-s4g%2Fimage-shrink_800%2FB4DZvHW1zXHYAg-%2F0%2F1768576212787%3Fe%3D2147483647%26v%3Dbeta%26t%3DsUoq7Py492jsT4jP1zou3dgr7vu2NjW0FBVxUc9XKeI" height="auto" class="m-0"&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.linkedin.com/posts/push-based_angular-typescript-js-activity-7417946368138358784-yhU6/" rel="noopener noreferrer" class="c-link"&gt;
            #angular #typescript #js | PushBased
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            TypeScript is changing forever! 

v6.0 will be the last JS-based release before the complete native Go rewrite in v7.0. TS Team is officially transitioning v6.0 into "Maintenance Mode" to focus on the port.

🔥 Major Breaking Changes to prepare for:
- Strict by Default: 𝘀𝘁𝗿𝗶𝗰𝘁: 𝘁𝗿𝘂𝗲 is finally the default.
- No More Legacy Modules: Support for 𝗮𝗺𝗱, 𝘂𝗺𝗱, and 𝘀𝘆𝘀𝘁𝗲𝗺𝗷𝘀 is being removed.
- Modern Targets: 𝘁𝗮𝗿𝗴𝗲𝘁 defaults to 𝗲𝘀&amp;lt;𝗰𝘂𝗿𝗿𝗲𝗻𝘁 𝘆𝗲𝗮𝗿&amp;gt; (Evergreen).
- Faster Builds: 𝘁𝘆𝗽𝗲𝘀 defaults to [ ] (stops auto-including every @𝘁𝘆𝗽𝗲𝘀 package).
- Enum Merging: Removed.
- Side Effects: 𝗻𝗼𝗨𝗻𝗰𝗵𝗲𝗰𝗸𝗲𝗱𝗦𝗶𝗱𝗲𝗘𝗳𝗳𝗲𝗰𝘁𝗜𝗺𝗽𝗼𝗿𝘁𝘀 defaults to 𝘁𝗿𝘂𝗲.

The Goal? 
A 10x faster compiler, but it requires shedding legacy weight.

Links: 
- Maintenance Mode (TS #62963): https://buff.ly/BRBTweG
- Deprecation List (TS #54500): https://buff.ly/Tb7QyGl 

The Angular Team has started preparing for it too:
https://buff.ly/Tb5KSBS 

#angular #typescript #js
          &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%2Fstatic.licdn.com%2Faero-v1%2Fsc%2Fh%2Fal2o9zrvru7aqj8e1x2rzsrca"&gt;
          linkedin.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;br&gt;
&lt;a href="https://github.com/angular/angular/pull/66578" rel="noopener noreferrer"&gt;Angular PR #66578&lt;/a&gt;
&lt;h2&gt;
  
  
  Miscellaneous
&lt;/h2&gt;

&lt;p&gt;The Angular DevTools provide a visualization of the Signal Graph. The latest version received an update and now gives a much better view on the resource, which in the end is a group of different Signals belonging together.&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2015832104722911325-347" src="https://platform.twitter.com/embed/Tweet.html?id=2015832104722911325"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2015832104722911325-347');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2015832104722911325&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;h2&gt;
  
  
  New Conferences
&lt;/h2&gt;

&lt;p&gt;Last but not least, ticket sales for Ng-India, India's largest Angular conference, have started.&lt;/p&gt;

&lt;p&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://www.ng-ind.com" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;ng-ind.com&lt;/span&gt;
          

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




&lt;p&gt;And again, if you are organizing a conference, please reach out to us so that we can promote it here.&lt;/p&gt;

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