<?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.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/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>
    <item>
      <title>Ng-News: Angular 21.1</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Fri, 23 Jan 2026 20:36:23 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-angular-211-4ofe</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-angular-211-4ofe</guid>
      <description>&lt;p&gt;Angular 21.1 is out with a smaller set of updates, but there are still some useful changes to cover. This episode highlights Signal Forms updates, experimental router auto-cleanup, and template syntax extensions.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

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

&lt;p&gt;As Signal Forms are still experimental, breaking changes within a minor and even patch are allowed and do happen.&lt;/p&gt;

&lt;p&gt;Probably the most impactful change was that the Field directive was renamed to FormField. You now use &lt;code&gt;FormField&lt;/code&gt; and &lt;code&gt;[formField]&lt;/code&gt;, while &lt;code&gt;Field&lt;/code&gt; and &lt;code&gt;[field]&lt;/code&gt; were completely removed and are no longer available. &lt;/p&gt;

&lt;p&gt;Technically speaking, that change and most others didn't come with the minor release but already happened within patch releases of the 21.0 range.&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-customer-registration&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;div&amp;gt;
      &amp;lt;mat-form-field&amp;gt;
        &amp;lt;input
          type="text"
          matInput
          [formField]="customerForm.firstname"
        /&amp;gt;
      &amp;lt;/mat-form-field&amp;gt;
    &amp;lt;/div&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="nx"&gt;FormField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;MatFormFieldModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;MatInputModule&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;CustomerRegistrationScreen&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;customerForm&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;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="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="nx"&gt;firstname&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;First name is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Auto Cleanup for Router-Provided Services
&lt;/h2&gt;

&lt;p&gt;We usually provide a service in root, that means we have a singleton, so one instance throughout the whole application, or we can provide it locally. That is usually done within a component and that instance goes down with the component and it is only available within that component and its children.&lt;/p&gt;

&lt;p&gt;But there is also another option, namely to provide a service on the router level. Until now, that service was instantiated when users entered that route but did not get destroyed and it was also not available in another route. So kind of a mixture between global and local.&lt;/p&gt;

&lt;p&gt;Angular 21.1 brings a new experimental router option for these services that auto-cleans route injectors, so the service behaves like one provided in a component and gets destroyed when users switch to a different route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Counter&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;count&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="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;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;takeUntilDestroyed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="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;count&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;c&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;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;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-counter&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;h1&amp;gt;Counter&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;Count: {{ count() }}&amp;lt;/p&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CounterPage&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;count&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;Counter&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;count&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;const&lt;/span&gt; &lt;span class="nx"&gt;appConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;provideRouter&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;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CounterPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Counter&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;withExperimentalAutoCleanupInjectors&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Template Syntax Extensions
&lt;/h2&gt;

&lt;p&gt;Angular's template allows us to inline code which looks like JavaScript but isn't. That's why features that JavaScript has but are missing in the template have to be implemented explicitly.&lt;/p&gt;

&lt;p&gt;Angular 21.1 extends its "template syntax" with the possibility of multiple consecutive switch case statements and supports the three dots, better known as the spread and rest operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;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;guest&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="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;member&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;subscriber&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;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="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-welcome&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;h2&amp;gt;Welcome&amp;lt;/h2&amp;gt;
    @switch (status()) {
      @case ('guest')
      @case ('anonymous') {
        &amp;lt;p&amp;gt;Please sign in&amp;lt;/p&amp;gt;
      }
    }`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Welcome&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="nx"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&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;guest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Miscellaneous
&lt;/h2&gt;

&lt;p&gt;Beyond the headline features, there are smaller improvements across the router and image-loading utilities. There are also reports of new MCP server tooling to better support running the dev server.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do We Continue
&lt;/h2&gt;

&lt;p&gt;As always, consult the changelog on GitHub and community write-ups for details and migration notes.&lt;/p&gt;

&lt;p&gt;The current public schedule suggests Angular 21.2 is planned for the week of February 23, with Angular 22 targeted for May and no further 21.x minors after that, but confirm in the official roadmap.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular/releases/tag/v21.1.0" rel="noopener noreferrer"&gt;Angular releases on GitHub&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/02: Frameworks in 2026, Competition among Frameworks, Angular Inside</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Tue, 20 Jan 2026 20:51:41 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2602-frameworks-in-2026-competition-among-frameworks-angular-inside-1jee</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2602-frameworks-in-2026-competition-among-frameworks-angular-inside-1jee</guid>
      <description>&lt;p&gt;This episode covers framework direction perspectives, a deep dive into Angular template type checking, and several community updates.&lt;/p&gt;

&lt;p&gt;📺 &lt;strong&gt;Watch the full episode on YouTube:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Ryan Carniato on 2026
&lt;/h2&gt;

&lt;p&gt;Ryan Carniato is the creator of Solid.js and has a good overview of what the various front-end frameworks are doing. He published an article where he gave his prediction for 2026.&lt;/p&gt;

&lt;p&gt;The rise of powerful SSR techniques (he mentioned React Server Components and Astro’s island architecture) led to separate code paths—one for the server and one for the client. Ryan expects frameworks to reduce that friction and coined the term isomorphic-first for this. In my opinion, if you want to see that reduced friction in action, Angular’s incremental hydration gets it right.&lt;/p&gt;

&lt;p&gt;Ryan sees asynchronicity as a central theme for the future. Frameworks will integrate async behavior more deeply rather than treating it as an add-on. Examples include Angular’s resource, and what React is doing under the “Async React” framing, which is a mix of techniques that work together.&lt;/p&gt;

&lt;p&gt;Lastly on AI: Ryan says meta-frameworks used to win by packaging tools together, but AI can now stitch those basic tools on its own, so that advantage is shrinking.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/playfulprogramming/javascript-frameworks-heading-into-2026-2hel" class="crayons-story__hidden-navigation-link"&gt;JavaScript Frameworks - Heading into 2026&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"&gt;
            &lt;img alt="Playful Programming 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.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F3314%2Ffd92caab-2014-431e-a19e-8ab47f2bf5ab.png" class="crayons-logo__image"&gt;
          &lt;/a&gt;

          &lt;a href="/ryansolid" 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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F186199%2Fa3d1cfed-a1ca-41cd-a146-9db4e65711d4.jpeg" alt="ryansolid profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ryansolid" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ryan Carniato
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ryan Carniato
                
              
              &lt;div id="story-author-preview-content-3102509" 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="/ryansolid" 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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F186199%2Fa3d1cfed-a1ca-41cd-a146-9db4e65711d4.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ryan Carniato&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" class="crayons-story__secondary fw-medium"&gt;Playful Programming&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/playfulprogramming/javascript-frameworks-heading-into-2026-2hel" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jan 5&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/javascript-frameworks-heading-into-2026-2hel" id="article-link-3102509"&gt;
          JavaScript Frameworks - Heading into 2026
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&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;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webperf"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webperf&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/frameworks"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;frameworks&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/javascript-frameworks-heading-into-2026-2hel" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;104&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/playfulprogramming/javascript-frameworks-heading-into-2026-2hel#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              28&lt;span class="hidden s:inline"&gt; comments&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;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&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;
  
  
  Mark Thompson at PodRocket
&lt;/h2&gt;

&lt;p&gt;Mark Thompson, DevRel on the Angular team, was a guest on the PodRocket podcast. It was aimed at a non-Angular audience, so most things that were discussed are broadly known, but at the end, Mark explained a little on how they see the competition. Every framework has a very similar feature set, and it is not that Angular wants to attract Svelte, React, or Vue users (or the other way around).&lt;/p&gt;

&lt;p&gt;Every framework looks at its user and optimizes the framework for their users. Or to put it short: when it comes to new features, it is more what the Angular community wants and not so much what React developers want from Angular.&lt;/p&gt;

&lt;p&gt;Apart from that, AI will bring changes in the way how developers write applications. They won't even care what framework is used, other things like MCP, context files could become more important.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular from the Inside (Angular Space)
&lt;/h2&gt;

&lt;p&gt;Angular from the Inside was the title of the Angular Space podcast. Armen Vardanyan had Matthieu Riegler from the Angular team as a guest.&lt;/p&gt;

&lt;p&gt;Matthieu showed how the template checks are actually working. He showed this in VSCode: Angular's compiler runs a special compilation just for the type check (via the language service for the VSCode integration) and then another compilation for the final application code.&lt;/p&gt;

&lt;p&gt;They also discussed things beyond compilation: the most requested PR, general insights into how the Angular team works internally, a PR explained in detail, and an overview of what is going to come for Angular 21.1 (which has already been released).&lt;/p&gt;

&lt;p&gt;An episode you don't want to miss if you are interested in learning some of Angular's internals.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/live/vz4LZAimZBc" rel="noopener noreferrer"&gt;https://www.youtube.com/live/vz4LZAimZBc&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tailwind Crisis
&lt;/h2&gt;

&lt;p&gt;Tailwind is also in the news, but unfortunately with sad news. Their business model was based on selling UI components. Unfortunately, you usually only discover those products if you visit their website and documentation, which is what we developers usually do... or rather, used to do. Because these days, AI applies the proper Tailwind classes automatically. Although Tailwind is used more than ever, 75% of the engineering team has been laid off because the company became a victim of the current AI trend. The good news is that Vercel and Google have contacted them and stepped in with sponsorships to help find a solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tailwindlabs/tailwindcss.com/pull/2388#issuecomment-3717222957" rel="noopener noreferrer"&gt;https://github.com/tailwindlabs/tailwindcss.com/pull/2388#issuecomment-3717222957&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

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

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





&lt;/p&gt;

&lt;p&gt;

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

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





&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Three v4
&lt;/h2&gt;

&lt;p&gt;Angular Three is a library from Chau Tran, which gives a deep integration of THREE.js into Angular. THREE.js is a very popular library for creating 3D graphics. Version 4 was released and the underlying renderer got completely rewritten.&lt;/p&gt;

&lt;p&gt;So if you are already using Angular Three, the blog post recommends that you treat version 4 as a complete fresh start.&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://angularthree.org" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;angularthree.org&lt;/span&gt;
          

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




&lt;h2&gt;
  
  
  Community Shoutout: ngx-dev-toolbar
&lt;/h2&gt;

&lt;p&gt;Shoutout to the community for new libraries. Alfredo Perez released ngx-dev-toolbar, which gives you a nice UI to apply common tasks, like toggling features, switching languages, mocking the network, and so on.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/alfredoperez" rel="noopener noreferrer"&gt;
        alfredoperez
      &lt;/a&gt; / &lt;a href="https://github.com/alfredoperez/ngx-dev-toolbar" rel="noopener noreferrer"&gt;
        ngx-dev-toolbar
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A powerful development toolbar for Angular applications to improve your developer productivity directly in the browser.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Angular Toolbar&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.npmjs.com/package/ngx-dev-toolbar" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a9f1d9812c2dc76a5c3364f55ba82119f2a160be23ee27ba54fe016286fad660/68747470733a2f2f62616467652e667572792e696f2f6a732f6e67782d6465762d746f6f6c6261722e737667" alt="npm version"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/ngx-dev-toolbar" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/f9b97e9f97f87cdbb353313e5b30644225588e27048b6efe8014d5c6ea49d111/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f6e67782d6465762d746f6f6c6261722e737667" alt="Downloads"&gt;&lt;/a&gt;
&lt;a href="https://github.com/alfredoperez/ngx-dev-toolbar/blob/main/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/aff024591238b7e91a90bd91195b0358a5c144f1988c5f6e0d33049c8a1e5c24/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f6c2f6e67782d6465762d746f6f6c6261722e737667" alt="License"&gt;&lt;/a&gt;
&lt;a href="https://angular.io/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/28dd8cad29614d60a904fa9d2b091b3ed7f117bab27606455b53a822dff03d5b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f416e67756c61722d31392532422d726564" alt="Angular"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A development toolbar for Angular 19+ applications that helps developers interact with the application more efficiently.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/alfredoperez/ngx-dev-toolbar/./docs/images/demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Falfredoperez%2Fngx-dev-toolbar%2F.%2Fdocs%2Fimages%2Fdemo.gif" alt="Toolbar Demo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why ngx-dev-toolbar?&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Toggle feature flags without backend changes&lt;/li&gt;
&lt;li&gt;Simulate complete i18n environments (locale, timezone, currency, RTL)&lt;/li&gt;
&lt;li&gt;Test product features and subscription tiers&lt;/li&gt;
&lt;li&gt;Switch themes on the fly&lt;/li&gt;
&lt;li&gt;Change user sessions effortlessly&lt;/li&gt;
&lt;li&gt;Mock network requests in real-time&lt;/li&gt;
&lt;li&gt;Test permission-based UI without backend changes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No more context switching or backend dependencies - everything you need is right in your browser!&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install ngx-dev-toolbar&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Quick Start&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Add the toolbar to your &lt;code&gt;app.config.ts&lt;/code&gt; alongside your other providers:&lt;/p&gt;
&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// app.config.ts&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;ApplicationConfig&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;isDevMode&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-s1"&gt;provideRouter&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/router'&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-s1"&gt;provideToolbar&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;'ngx-dev-toolbar'&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;const&lt;/span&gt; &lt;span class="pl-s1"&gt;appConfig&lt;/span&gt;: &lt;span class="pl-smi"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;providers&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;
    &lt;span class="pl-en"&gt;provideRouter&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;appRoutes&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;provideToolbar&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-c1"&gt;enabled&lt;/span&gt;: &lt;span class="pl-en"&gt;isDevMode&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;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;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 class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// main.ts&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/alfredoperez/ngx-dev-toolbar" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;&lt;em&gt;If you have written a new library or are organizing a conference, please let us know. We are going to announce it here.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>angular</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Ng-News 26/01: Ng-Poland Outtakes - Keynote and Q&amp;A</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Mon, 12 Jan 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2601-ng-poland-outtakes-keynote-and-qa-ack</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2601-ng-poland-outtakes-keynote-and-qa-ack</guid>
      <description>&lt;p&gt;The Angular team reveals their vision for AI-powered development workflows using MCP Servers, where LLMs generate, test, and debug Angular applications autonomously. Plus, learn about Signal Forms migration paths, the new &lt;code&gt;@ng-forge/dynamic-forms&lt;/code&gt; library, and &lt;a href="https://ngrx.io/" rel="noopener noreferrer"&gt;NgRx&lt;/a&gt; 21.&lt;/p&gt;

&lt;p&gt;📺 &lt;strong&gt;Watch the full episode on YouTube:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt;This episode covers news from around Christmas until New Year's Eve. The next episode will focus solely on events from 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ng-Poland Keynote
&lt;/h2&gt;

&lt;p&gt;Ng-Poland took place in November, and videos from both the keynote and the Q&amp;amp;A session with the Angular team are now available on YouTube. Here are the main takeaways.&lt;/p&gt;

&lt;p&gt;The keynote discussed features introduced in Angular 21, which we covered in a previous episode. The keynote, however, was mainly about AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  MCP Server Workflow
&lt;/h3&gt;

&lt;p&gt;First, Jeremy Elbourn explained an AI-supported workflow that we can expect.&lt;/p&gt;

&lt;p&gt;With the help of Angular's MCP Server (Model Context Protocol), the LLM would first generate modern Angular code. It would also start the application and test the produced code via &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright's&lt;/a&gt; MCP Server.&lt;/p&gt;

&lt;p&gt;If there was a bug, the Angular MCP could connect to the running browser and collect the context of the running application—its state, so to speak—to find the error and fix it.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI as User
&lt;/h3&gt;

&lt;p&gt;Second, Alex Rickabaugh, tech lead of the Angular framework, discussed what changes the framework requires to be prepared for what might come. In the past, they have been doing user studies with real developers, where they showed them certain APIs that they wanted to introduce and then observed how those developers were dealing with them. Nowadays, they also see AI as an end-user and have a similar approach.&lt;/p&gt;

&lt;p&gt;Alex also mentioned that they have to prepare for more dynamic UIs. They don't have anything concrete yet, but they recommend checking out community solutions like &lt;a href="https://hashbrown.dev/" rel="noopener noreferrer"&gt;Hashbrown&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keynote video:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Q&amp;amp;A Session
&lt;/h2&gt;

&lt;p&gt;Next, there was also the Q&amp;amp;A. Here are three interesting takeaways:&lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;There was a question on how to protect your codebase from malicious libraries, especially from those kinds of attacks which we have seen in the second half of 2025. Here, we can just take a look at the measures Angular does for its own project.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They use &lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;&lt;code&gt;pnpm&lt;/code&gt;&lt;/a&gt;, which has a lot of advantages over &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;&lt;code&gt;npm&lt;/code&gt;&lt;/a&gt;. For example it doesn't automatically execute post-install scripts.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.renovatebot.com/" rel="noopener noreferrer"&gt;Renovate&lt;/a&gt; is responsible for managing the upgrades and it has a setting which doesn't install packages until they've been published for a certain period of time, for example 2 days.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Generally speaking, studying the Angular repo itself will show further measures for improving security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Angular Material and UI Libraries
&lt;/h3&gt;

&lt;p&gt;There was also a question about &lt;code&gt;@angular/aria&lt;/code&gt; and how it fits together with &lt;a href="https://material.angular.io/" rel="noopener noreferrer"&gt;Angular Material&lt;/a&gt;. Jeremy said that the days of having full-blown UI libraries which might be a little hard to customize are over.&lt;/p&gt;

&lt;p&gt;The current trend is more towards customizable individual design systems, and this is why &lt;code&gt;@angular/aria&lt;/code&gt; is strong. It only provides the behavior, the visual is completely up to the developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signal Forms Migration
&lt;/h3&gt;

&lt;p&gt;And there were, of course, also a few questions about Signal Forms.&lt;/p&gt;

&lt;p&gt;The migration from Reactive Forms or Template-Driven Forms is also important. At the moment, we do have the possibility to reuse &lt;code&gt;FormControl&lt;/code&gt; or &lt;code&gt;FormGroup&lt;/code&gt; from Reactive Forms in Signal Forms, but Alex also announced that there will be a path towards the other direction: Reactive Forms will be able to run Signal Forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A video:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Forms
&lt;/h2&gt;

&lt;p&gt;There is this idea of having dynamic forms. So you provide a certain set of metadata, which includes the value, the validation rules, but also the UI type (select box, input field, radio button, or checkbox), and then the form could be generated dynamically.&lt;/p&gt;

&lt;p&gt;For the old form system, there were some libraries which did that. A prominent one was &lt;a href="https://formly.dev/" rel="noopener noreferrer"&gt;ngx-formly&lt;/a&gt;. At the moment, it is not clear if ngx-formly will provide support for Signal Forms and, if so, how it will do so.&lt;/p&gt;

&lt;p&gt;But there is a new library, built from the beginning for Signal Forms. Its name is &lt;code&gt;@ng-forge/dynamic-forms&lt;/code&gt;. It comes with an integration of common UI libraries: &lt;a href="https://material.angular.io/" rel="noopener noreferrer"&gt;Angular Material&lt;/a&gt;, &lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt;, but also &lt;a href="https://primeng.org/" rel="noopener noreferrer"&gt;PrimeNG&lt;/a&gt; and &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&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.ng-forge.com/dynamic-forms/what-is-dynamic-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%2Fng-forge.com%2Fdynamic-forms%2Fog-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://www.ng-forge.com/dynamic-forms/what-is-dynamic-forms" rel="noopener noreferrer" class="c-link"&gt;
            ng-forge - Dynamic Forms for Angular
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Forms are boring. Your code shouldn't be. Write the config, we handle the rest. Type-safe, signal-native, zero boilerplate Angular forms.
          &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.ng-forge.com%2Fdynamic-forms%2Ffavicon.svg"&gt;
          ng-forge.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;h2&gt;
  
  
  NgRx 21
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ngrx.io/" rel="noopener noreferrer"&gt;NgRx&lt;/a&gt;, the most used library for state management in Angular, was released in version 21. It brings a new website, the events plugin for the &lt;a href="https://ngrx.io/guide/signals/signal-store" rel="noopener noreferrer"&gt;SignalStore&lt;/a&gt; went stable, and further improvements.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ngrx/announcing-ngrx-21-celebrating-a-10-year-journey-with-a-fresh-new-look-and-ngrxsignalsevents-5ekp" class="crayons-story__hidden-navigation-link"&gt;Announcing NgRx 21: Celebrating a 10 Year Journey with a fresh new look and @ngrx/signals/events&lt;/a&gt;


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

          &lt;a href="/timdeschryver" 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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F106988%2F32b9bdaa-a0d6-426a-9040-cec6b89a75dc.jpg" alt="timdeschryver profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/timdeschryver" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Tim Deschryver
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Tim Deschryver
                
              
              &lt;div id="story-author-preview-content-3114018" 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="/timdeschryver" 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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F106988%2F32b9bdaa-a0d6-426a-9040-cec6b89a75dc.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Tim Deschryver&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/ngrx" class="crayons-story__secondary fw-medium"&gt;NgRx&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/ngrx/announcing-ngrx-21-celebrating-a-10-year-journey-with-a-fresh-new-look-and-ngrxsignalsevents-5ekp" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 22 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ngrx/announcing-ngrx-21-celebrating-a-10-year-journey-with-a-fresh-new-look-and-ngrxsignalsevents-5ekp" id="article-link-3114018"&gt;
          Announcing NgRx 21: Celebrating a 10 Year Journey with a fresh new look and @ngrx/signals/events
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ngrx"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ngrx&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/angular"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;angular&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ngrx/announcing-ngrx-21-celebrating-a-10-year-journey-with-a-fresh-new-look-and-ngrxsignalsevents-5ekp" 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="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;23&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ngrx/announcing-ngrx-21-celebrating-a-10-year-journey-with-a-fresh-new-look-and-ngrxsignalsevents-5ekp#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; 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;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

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

&lt;/div&gt;




</description>
      <category>webdev</category>
      <category>programming</category>
      <category>angular</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Ng-News: Angular in 2025</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Fri, 02 Jan 2026 20:29:42 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-angular-in-2025-307a</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-angular-in-2025-307a</guid>
      <description>&lt;p&gt;The main topics this year were the Signal evolution—specifically the polish of the &lt;strong&gt;Resource API&lt;/strong&gt; and &lt;strong&gt;Signal Forms&lt;/strong&gt;—and the massive shift toward &lt;strong&gt;AI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We also used a new layout for this video. Please let us know what you think about it—either here or in the YouTube comments.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

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

&lt;p&gt;Let's start with the headline feature: &lt;strong&gt;Signal Forms&lt;/strong&gt;. They are fairly young. The team announced them at ng-Poland in 2024, and it took a full year until they landed in Angular 21.&lt;/p&gt;

&lt;p&gt;We waited a long time for Signal Forms. Enterprise applications rely heavily on forms; some might even say a frontend application is just a collection of forms.&lt;/p&gt;

&lt;p&gt;Signal Forms succeed both template-driven and Reactive forms. They combine the advantages of the old systems but in a modern, signal-based way. In template-driven forms, the form wrote directly into the data structure we provided. With Signal Forms, that structure needs to reside inside a Signal.&lt;/p&gt;

&lt;p&gt;Validation works like it did in Reactive forms: we define it in TypeScript. But here again, the validation system is far better than the old one. There is almost no limit on what you can do with it.&lt;/p&gt;

&lt;p&gt;The complexity with custom controls also disappears. We no longer need to implement the clumsy &lt;code&gt;ControlValueAccessor&lt;/code&gt; interface. Instead, we bind a property called &lt;code&gt;value&lt;/code&gt; via the &lt;code&gt;model&lt;/code&gt; function, and that's it.&lt;/p&gt;

&lt;p&gt;Signal Forms are still experimental, but the Angular team stated they plan to remove the experimental status soon.&lt;/p&gt;

&lt;p&gt;Here's a full example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserData&lt;/span&gt; &lt;span class="o"&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="kr"&gt;number&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="nl"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="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-button-checkbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    @if (value()) {
      &amp;lt;button (click)="value.set(true)"&amp;gt;Subscribe to Newsletter&amp;lt;/button&amp;gt;
    } @else {
      &amp;lt;button (click)="value.set(false)"&amp;gt;Unsubscribe from Newsletter&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;ButtonCheckbox&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="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="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="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="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;`&amp;lt;form&amp;gt;
    &amp;lt;input [field]="userForm.id" type="number" /&amp;gt;
    &amp;lt;input [field]="userForm.firstname" /&amp;gt;
    &amp;lt;input [field]="userForm.lastname" /&amp;gt;
    &amp;lt;app-button-checkbox [field]="userForm.subscribe" /&amp;gt;
  &amp;lt;/form&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="nx"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ButtonCheckbox&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;UserForm&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;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserData&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;1&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;Smith&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;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;userData&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;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;Id is required&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;firstname&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;Firstname is required&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;lastname&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;Lastname is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The &lt;code&gt;resource&lt;/code&gt; appeared in version 19 (late 2024), but in the minor release of 19.2, we got the third primitive: the &lt;strong&gt;&lt;code&gt;httpResource&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The resource bridges the gap whenever a Signal depends on an asynchronous task. In most cases, that task is an HTTP Request, which makes the &lt;code&gt;httpResource&lt;/code&gt; vital.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;httpResource&lt;/code&gt; uses the &lt;code&gt;HttpClient&lt;/code&gt; under the hood. This means all interceptors still work the same. That doesn't necessarily mean everyone uses the &lt;code&gt;HttpClient&lt;/code&gt;. If we use a generated data client service (via OpenAPI) that exposes an Observable, we use &lt;strong&gt;&lt;code&gt;rxResource&lt;/code&gt;&lt;/strong&gt; instead.&lt;/p&gt;

&lt;p&gt;In Angular 20, the resources received a final overhaul. For example, they now throw an error if we access the value in an error state, and the status values became strict union types. Like Signal Forms, the resources are still experimental. Hopefully, that will change soon, maybe even in a minor release of version 21.&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;page&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageSize&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;10&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;holidays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;httpResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/holidays&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;page&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="c1"&gt;// similar to httpClient.get('/holidays', { params: { ... } })&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="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="nx"&gt;parseHolidays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  AI
&lt;/h2&gt;

&lt;p&gt;And of course, AI. We saw massive investment here.&lt;/p&gt;

&lt;p&gt;The basics: We received an &lt;strong&gt;MCP Server&lt;/strong&gt; which improves with each release. Most importantly, it contains instructions for the LLM to produce modern Angular code—Signals, template control syntax, standalone components, etc.&lt;/p&gt;

&lt;p&gt;But AI and Angular go much deeper. The Angular team researches what a framework needs to be "AI-ready." They try to optimize the API not just for us users, but also for an AI agent. They run several tests and even wrote a &lt;strong&gt;Codegen Scorer&lt;/strong&gt; to evaluate the results.&lt;/p&gt;

&lt;p&gt;Furthermore, we see that &lt;strong&gt;Gemini&lt;/strong&gt; (Google's LLM) made big leaps this year. If you are the Angular team, and you sit in the same company that lives and breathes AI, you benefit from a good environment and access to all necessary resources.&lt;/p&gt;

&lt;p&gt;But because of this huge investment in AI, we also had to accept that other features might not have received the love they needed.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Miscellaneous
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Zoneless
&lt;/h3&gt;

&lt;p&gt;What else happened? &lt;strong&gt;Zoneless&lt;/strong&gt; became not just stable, but also the default mode in Angular 21. If we consider the time span from developer experience to stable and then default, it happened within just one major version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vitest
&lt;/h3&gt;

&lt;p&gt;Speaking of fast, &lt;strong&gt;Vitest&lt;/strong&gt; skipped "developer preview" and "stable" and jumped from experimental directly to default. That also happened in Angular 21. We finally have a top-tier testing framework and don't have to hide from other ecosystems.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;@angular/aria&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Then came &lt;strong&gt;@angular/aria&lt;/strong&gt;. It follows the trend where we want full control over our UI components but still want help with behavior. This is exactly what &lt;code&gt;@angular/aria&lt;/code&gt; does. It gives you a set of directives that promise proper accessibility behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deprecation of &lt;code&gt;@angular/animations&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, we saw a deprecation with &lt;strong&gt;@angular/animations&lt;/strong&gt;. We no longer need a separate package or the complex DSL. The new, minimalistic animation support lives directly in the template. We now use &lt;strong&gt;&lt;code&gt;animate.enter&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;animate.leave&lt;/code&gt;&lt;/strong&gt; to handle entry and exit transitions right where we define the HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  Statistics &amp;amp; Perception
&lt;/h3&gt;

&lt;p&gt;In terms of download statistics, the "Angular Renaissance" has not yet materialized into a massive spike. Downloads continue to rise, but they do so steadily.&lt;/p&gt;

&lt;p&gt;Generally, the perception of Angular has turned positive again. However, real-world effects take time. Enterprises—our main user base—move slowly. Many prefer to wait until the transition to "Modern Angular" is fully complete before upgrading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outlook 2026
&lt;/h2&gt;

&lt;p&gt;This brings us to the outlook. What can we expect in 2026?&lt;/p&gt;

&lt;p&gt;I expect—and hope—that &lt;strong&gt;Signal Forms&lt;/strong&gt; and the &lt;strong&gt;Resource API&lt;/strong&gt; will finally hit stable status.&lt;/p&gt;

&lt;p&gt;Last year, I predicted &lt;strong&gt;Selectorless&lt;/strong&gt; components and a new &lt;strong&gt;Authoring Format&lt;/strong&gt;. Neither happened in 2025, so I will carry them over to next year. "Selectorless" means we refer directly to a component class in the template, requiring only one import. As for the authoring format... nobody knows. It could be &lt;strong&gt;Signal Components&lt;/strong&gt;, a switch from classes to functions, or something else entirely. We will see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ng-News in Spanish and Portuguese
&lt;/h2&gt;

&lt;p&gt;Last but not least, ng-news now exists in &lt;strong&gt;Spanish&lt;/strong&gt; and &lt;strong&gt;Brazilian Portuguese&lt;/strong&gt; versions. I am really happy that creators from Latin America approached me and joined the project. These are separate YouTube channels, and I hope we add even more languages next year.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@ng-news-es" rel="noopener noreferrer"&gt;https://www.youtube.com/@ng-news-es&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@ng-news-BRAZIL" rel="noopener noreferrer"&gt;https://www.youtube.com/@ng-news-BRAZIL&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So it looks good for another year of ng-news. A huge thanks to you—especially for your support when you share, like, and recommend the it to colleagues. That keeps ng-news rolling.&lt;/p&gt;

&lt;p&gt;We wish you a successful and healthy New Year.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>angular</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Ng-News 25/50: Auto-Destroy for Router Providers, Signal Forms</title>
      <dc:creator>ng-news</dc:creator>
      <pubDate>Mon, 22 Dec 2025 15:07:36 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/ng-news-2550-auto-destroy-for-router-providers-signal-forms-27ko</link>
      <guid>https://dev.to/playfulprogramming-angular/ng-news-2550-auto-destroy-for-router-providers-signal-forms-27ko</guid>
      <description>&lt;p&gt;Angular will bring auto-destroy for router providers and more updates around Signal Forms. The community shares new articles, talks, and practical examples.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Auto-Destroy for Router Providers
&lt;/h2&gt;

&lt;p&gt;A new feature for the router will land in Angular 21.1. This might surprise some developers, because many assumed this behavior was already standard.&lt;/p&gt;

&lt;p&gt;If a service is provided only at component level, so not in root, the service gets destroyed together with the component. This does not happen when a service is provided in the router. In that case, it stays alive across navigations. With Angular 21.1, it will become possible to destroy such services when users navigate away. The PR exists, but it has not been merged yet.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/angular/angular/pull/65991" 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(router): add controls for route cleanup
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#65991&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/atscott" 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%2F479713%3Fv%3D4" alt="atscott avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/atscott" rel="noopener noreferrer"&gt;atscott&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/angular/angular/pull/65991" rel="noopener noreferrer"&gt;&lt;time&gt;Dec 10, 2025&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;This commit introduces a new feature to automatically destroy &lt;code&gt;EnvironmentInjector&lt;/code&gt;s associated with routes that are no longer active or stored. This helps in managing memory by releasing resources held by unused injectors.&lt;/p&gt;
&lt;p&gt;Key changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Added &lt;code&gt;shouldDestroyInjector&lt;/code&gt; and &lt;code&gt;retrieveStoredRouteHandles&lt;/code&gt; to &lt;code&gt;RouteReuseStrategy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Introduced &lt;code&gt;withExperimentalAutoCleanupInjectors&lt;/code&gt; provider function to opt-in to this feature.&lt;/li&gt;
&lt;li&gt;Implemented a "mark and sweep" algorithm to identify and destroy unused injectors.&lt;/li&gt;
&lt;li&gt;Added a dev mode warning if the strategy implements destruction methods but the feature is not enabled.&lt;/li&gt;
&lt;li&gt;Added integration tests to verify the behavior.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This commit also &lt;code&gt;destroyDetachedRouteHandle&lt;/code&gt;, a standalone function that allows developers to explicitly destroy the component associated with a &lt;code&gt;DetachedRouteHandle&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We chose to implement this as a standalone function rather than adding a &lt;code&gt;destroy()&lt;/code&gt; method to the &lt;code&gt;DetachedRouteHandle&lt;/code&gt; type to avoid breaking changes. Currently, &lt;code&gt;DetachedRouteHandle&lt;/code&gt; is defined as &lt;code&gt;{}&lt;/code&gt;, and many applications mock it as such. Adding a required method to the interface would break these existing tests and usages.&lt;/p&gt;
&lt;p&gt;By using a standalone function, we can safely cast the handle to its internal type and invoke destruction without altering the public contract of the handle itself.&lt;/p&gt;
&lt;p&gt;This feature is particularly useful for &lt;code&gt;RouteReuseStrategy&lt;/code&gt; implementations that need to drop stored handles and ensure the associated components are properly cleaned up to prevent memory leaks.&lt;/p&gt;
&lt;p&gt;resolves #27290
resolves #37095
resolves #15873&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/65991" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;




&lt;h2&gt;
  
  
  Signal Forms Guide with &lt;code&gt;compatForm&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Mateusz Stefańczyk from House of Angular published another long article on Signal Forms, adding to the growing list of community content. The article is interesting because it also covers compatForm. This function can work with a Signal as well as with a FormControl or FormGroup. It therefore offers a migration path from existing forms to Signal Forms.&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://angular.love/signal-forms-in-angular-21-complete-guide" 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;h2&gt;
  
  
  Alex Rickabaugh @ Jason Lengstorf
&lt;/h2&gt;

&lt;p&gt;Alex Rickabaugh, tech lead of the Angular framework, was a guest on a livestream with Jason Lengstorf. The session had two parts. The first part focused on the underlying concepts and the motivation behind Signal Forms. The second part moved into live coding.&lt;/p&gt;

&lt;p&gt;From Alex’s perspective, Signal Forms are clearly the direction forward. He also gave a good overview of the three different maturity states the Angular team uses for features.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;...And so that's really what &lt;strong&gt;experimental&lt;/strong&gt; is for us is...hey, this is not fully baked yet, but we're letting you on to it early because we really value that kind of on the ground feedback about how it's working for real use cases.&lt;/p&gt;

&lt;p&gt;Then we have &lt;strong&gt;developer preview&lt;/strong&gt;, which is more of, like a release extended release candidate. Like we think this is feature complete, this could ship as stable, but we want to give developers one more chance to kind of bang on it and see what breaks.&lt;/p&gt;

&lt;p&gt;If we release an API as &lt;strong&gt;stable&lt;/strong&gt;,... if we are going to make a breaking change to it, we give you two major versions to migrate, or from the time we deprecate something to the time we remove it. Or we have some kind of auto migration for you that will make sure that as you update the code, it kind of follows along.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Ng-Glühwein
&lt;/h2&gt;

&lt;p&gt;ng-Glühwein, an Angular conference in Vienna, took place for the third year in a row, and the recordings are already available on YouTube. The talks covered a wide range of topics.&lt;/p&gt;

&lt;p&gt;Push-based, as the organizer, contributed three talks. Julian Jandl and Christopher Holder spoke about performance. Adrian Romanski covered accessibility. Thomas Trajan presented modern strategies for dynamic component loading. Michael Hablich gave an AI-focused talk on the DevTools MCP server. Elise Patrikainen spoke about Angular resources.&lt;br&gt;
Members of the Angular team were also present. Matthieu Riegler talked about Signals, and Alan Agius covered secure management of third-party libraries.&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.youtube.com/@push-based/videos" 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%2Fyt3.googleusercontent.com%2FUd3_C5logRhAp5eIIoEALjj4P6M_OwmD2AlZBlJMF_IGh0kFLv6MT4wd2FFEeYYKom1u_K1J7Q%3Ds900-c-k-c0x00ffffff-no-rj" 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.youtube.com/@push-based/videos" rel="noopener noreferrer" class="c-link"&gt;
            Push-Based - YouTube
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Push-Based is a close knit group of IT experts offering their knowledge and services in #Angular #RxJS #NestJS #JavaScript #TypeScript #webperf and more.
          &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.youtube.com%2Fs%2Fdesktop%2F7cf77294%2Fimg%2Ffavicon.ico"&gt;
          youtube.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;h2&gt;
  
  
  Ng-Belgrade 2026
&lt;/h2&gt;

&lt;p&gt;Ng-Belgrade has announced its revival for next year. The event will take place on May 7th, and ticket sales are already open.&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://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="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://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"&gt;
          angularbelgrade.org
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




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