Bumps [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) from 21.2.17 to 22.0.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/angular/angular/releases">@angular/core's releases</a>.</em></p> <blockquote> <h2>22.0.2</h2> <h3>common</h3> <table> <thead> <tr> <th>Commit</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="94ea403563"><img src="https://img.shields.io/badge/94ea403563-fix-green" alt="fix - 94ea403563" /></a></td> <td>escape anchor fragment in shadow DOM name selector</td> </tr> <tr> <td><a href="6c1f3e9d49"><img src="https://img.shields.io/badge/6c1f3e9d49-fix-green" alt="fix - 6c1f3e9d49" /></a></td> <td>skip transfer cache for uncacheable HTTP traffic (<a href="https://github.com/angular/angular/tree/HEAD/packages/core/issues/69316">#69316</a>)</td> </tr> </tbody> </table> <h3>compiler</h3> <table> <thead> <tr> <th>Commit</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="6f1171991a"><img src="https://img.shields.io/badge/6f1171991a-fix-green" alt="fix - 6f1171991a" /></a></td> <td>restrict possible event handler check to property names longer than 2 characters</td> </tr> </tbody> </table> <h3>core</h3> <table> <thead> <tr> <th>Commit</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="528a34f766"><img src="https://img.shields.io/badge/528a34f766-fix-green" alt="fix - 528a34f766" /></a></td> <td>avoid caching missing locale data</td> </tr> <tr> <td><a href="e17e8d5422"><img src="https://img.shields.io/badge/e17e8d5422-fix-green" alt="fix - e17e8d5422" /></a></td> <td>escape overlapping comment delimiters in escapeCommentText</td> </tr> <tr> <td><a href="59dea13f80"><img src="https://img.shields.io/badge/59dea13f80-fix-green" alt="fix - 59dea13f80" /></a></td> <td>guard against DOM clobbering in declareExperimentalWebMcpTool</td> </tr> <tr> <td><a href="3a48abc15c"><img src="https://img.shields.io/badge/3a48abc15c-fix-green" alt="fix - 3a48abc15c" /></a></td> <td>preserve leave animation for sibling instances sharing a TNode</td> </tr> <tr> <td><a href="93d0a5f95c"><img src="https://img.shields.io/badge/93d0a5f95c-fix-green" alt="fix - 93d0a5f95c" /></a></td> <td>prevent unsubscribe during emit from throwing off other listeners</td> </tr> <tr> <td><a href="b32ee7ceb3"><img src="https://img.shields.io/badge/b32ee7ceb3-fix-green" alt="fix - b32ee7ceb3" /></a></td> <td>treat iframe credentialless as security-sensitive</td> </tr> <tr> <td><a href="f902d1d35e"><img src="https://img.shields.io/badge/f902d1d35e-perf-orange" alt="perf - f902d1d35e" /></a></td> <td>detect existing signal dependency without checking all producer links</td> </tr> </tbody> </table> <h3>http</h3> <table> <thead> <tr> <th>Commit</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="6867f77ec7"><img src="https://img.shields.io/badge/6867f77ec7-fix-green" alt="fix - 6867f77ec7" /></a></td> <td>distinguish repeated transfer cache params</td> </tr> <tr> <td><a href="7ef1399068"><img src="https://img.shields.io/badge/7ef1399068-fix-green" alt="fix - 7ef1399068" /></a></td> <td>skip transfer cache for fetch credentialed requests (<a href="https://github.com/angular/angular/tree/HEAD/packages/core/issues/69316">#69316</a>)</td> </tr> </tbody> </table> <h3>migrations</h3> <table> <thead> <tr> <th>Commit</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="15314c1736"><img src="https://img.shields.io/badge/15314c1736-fix-green" alt="fix - 15314c1736" /></a></td> <td>migration skip any target are not build or test</td> </tr> </tbody> </table> <h2>22.0.1</h2> <h3>common</h3> <table> <thead> <tr> <th>Commit</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="c4b5fa3c92"><img src="https://img.shields.io/badge/c4b5fa3c92-fix-green" alt="fix - c4b5fa3c92" /></a></td> <td>escape CSS string-terminating characters in escapeCssUrl</td> </tr> <tr> <td><a href="dfff57ede9"><img src="https://img.shields.io/badge/dfff57ede9-fix-green" alt="fix - dfff57ede9" /></a></td> <td>Limits date format string length</td> </tr> <tr> <td><a href="3c2892c8df"><img src="https://img.shields.io/badge/3c2892c8df-fix-green" alt="fix - 3c2892c8df" /></a></td> <td>prevent prototype pollution in formatDateTime</td> </tr> <tr> <td><a href="1d87c49f6e"><img src="https://img.shields.io/badge/1d87c49f6e-fix-green" alt="fix - 1d87c49f6e" /></a></td> <td>use cryptographically secure SHA-256 for transfer cache key generation</td> </tr> </tbody> </table> <h3>compiler</h3> <table> <thead> <tr> <th>Commit</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="1ee224ca30"><img src="https://img.shields.io/badge/1ee224ca30-fix-green" alt="fix - 1ee224ca30" /></a></td> <td>disallow i18n event attributes</td> </tr> <tr> <td><a href="a56f1cdf8f"><img src="https://img.shields.io/badge/a56f1cdf8f-fix-green" alt="fix - a56f1cdf8f" /></a></td> <td>more robust logic to check if regex can be optimized</td> </tr> <tr> <td><a href="5946c18275"><img src="https://img.shields.io/badge/5946c18275-fix-green" alt="fix - 5946c18275" /></a></td> <td>sanitize <code>href</code>/<code>xlink:href</code> attributes of any element of the MathML namespace</td> </tr> <tr> <td><a href="393b84caf8"><img src="https://img.shields.io/badge/393b84caf8-fix-green" alt="fix - 393b84caf8" /></a></td> <td>sanitize two-way properties</td> </tr> </tbody> </table> <h3>compiler-cli</h3> <table> <thead> <tr> <th>Commit</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="3d9ca2f173"><img src="https://img.shields.io/badge/3d9ca2f173-fix-green" alt="fix - 3d9ca2f173" /></a></td> <td>bind switch exhaustive check expressions</td> </tr> </tbody> </table> <h3>core</h3> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/angular/angular/blob/main/CHANGELOG.md">@angular/core's changelog</a>.</em></p> <blockquote> <h1>22.0.2 (2026-06-17)</h1> <h3>common</h3> <table> <thead> <tr> <th>Commit</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="94ea403563">94ea403563</a></td> <td>fix</td> <td>escape anchor fragment in shadow DOM name selector</td> </tr> <tr> <td><a href="6c1f3e9d49">6c1f3e9d49</a></td> <td>fix</td> <td>skip transfer cache for uncacheable HTTP traffic (<a href="https://redirect.github.com/angular/angular/pull/69316">#69316</a>)</td> </tr> </tbody> </table> <h3>compiler</h3> <table> <thead> <tr> <th>Commit</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="6f1171991a">6f1171991a</a></td> <td>fix</td> <td>restrict possible event handler check to property names longer than 2 characters</td> </tr> </tbody> </table> <h3>core</h3> <table> <thead> <tr> <th>Commit</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="528a34f766">528a34f766</a></td> <td>fix</td> <td>avoid caching missing locale data</td> </tr> <tr> <td><a href="e17e8d5422">e17e8d5422</a></td> <td>fix</td> <td>escape overlapping comment delimiters in escapeCommentText</td> </tr> <tr> <td><a href="59dea13f80">59dea13f80</a></td> <td>fix</td> <td>guard against DOM clobbering in declareExperimentalWebMcpTool</td> </tr> <tr> <td><a href="3a48abc15c">3a48abc15c</a></td> <td>fix</td> <td>preserve leave animation for sibling instances sharing a TNode</td> </tr> <tr> <td><a href="93d0a5f95c">93d0a5f95c</a></td> <td>fix</td> <td>prevent unsubscribe during emit from throwing off other listeners</td> </tr> <tr> <td><a href="b32ee7ceb3">b32ee7ceb3</a></td> <td>fix</td> <td>treat iframe credentialless as security-sensitive</td> </tr> <tr> <td><a href="f902d1d35e">f902d1d35e</a></td> <td>perf</td> <td>detect existing signal dependency without checking all producer links</td> </tr> </tbody> </table> <h3>http</h3> <table> <thead> <tr> <th>Commit</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="6867f77ec7">6867f77ec7</a></td> <td>fix</td> <td>distinguish repeated transfer cache params</td> </tr> <tr> <td><a href="7ef1399068">7ef1399068</a></td> <td>fix</td> <td>skip transfer cache for fetch credentialed requests (<a href="https://redirect.github.com/angular/angular/pull/69316">#69316</a>)</td> </tr> </tbody> </table> <h3>migrations</h3> <table> <thead> <tr> <th>Commit</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="15314c1736">15314c1736</a></td> <td>fix</td> <td>migration skip any target are not build or test</td> </tr> </tbody> </table> <h1>22.1.0-next.0 (2026-06-10)</h1> <h2>Deprecations</h2> <h3>http</h3> <ul> <li><code>HttpClient.jsonp</code>, <code>HttpClientJsonpModule</code>, and related JSONP classes/functions are deprecated. Use standard HTTP requests instead.</li> </ul> <h3>common</h3> <table> <thead> <tr> <th>Commit</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="1ad6824d0d">1ad6824d0d</a></td> <td>fix</td> <td>skip transfer cache for uncacheable HTTP traffic (<a href="https://redirect.github.com/angular/angular/pull/69017">#69017</a>)</td> </tr> </tbody> </table> <h3>compiler</h3> <table> <thead> <tr> <th>Commit</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="25c744c4d0">25c744c4d0</a></td> <td>fix</td> <td>support foreign components defined outside top-level scope</td> </tr> </tbody> </table> <h3>compiler-cli</h3> <table> <thead> <tr> <th>Commit</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><a href="aeb55c8bc1">aeb55c8bc1</a></td> <td>fix</td> <td>allow passing uninvoked signals as foreign component props</td> </tr> <tr> <td><a href="7c60a98b3c">7c60a98b3c</a></td> <td>fix</td> <td>support import aliases in foreignImports (<a href="https://redirect.github.com/angular/angular/pull/68674">#68674</a>)</td> </tr> </tbody> </table> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="152601ed94"><code>152601e</code></a> refactor(core): add <code>childSignalProp</code> to <code>ReactiveNodeKind</code></li> <li><a href="59dea13f80"><code>59dea13</code></a> fix(core): guard against DOM clobbering in declareExperimentalWebMcpTool</li> <li><a href="81cb4570b2"><code>81cb457</code></a> refactor(router): Add handling for ActivatedRoute-scoped injector</li> <li><a href="f902d1d35e"><code>f902d1d</code></a> perf(core): detect existing signal dependency without checking all producer l...</li> <li><a href="e17e8d5422"><code>e17e8d5</code></a> fix(core): escape overlapping comment delimiters in escapeCommentText</li> <li><a href="0f1cfe3082"><code>0f1cfe3</code></a> build: update cross-repo angular dependencies to v22.0.2</li> <li><a href="b32ee7ceb3"><code>b32ee7c</code></a> fix(core): treat iframe credentialless as security-sensitive</li> <li><a href="93d0a5f95c"><code>93d0a5f</code></a> fix(core): prevent unsubscribe during emit from throwing off other listeners</li> <li><a href="528a34f766"><code>528a34f</code></a> fix(core): avoid caching missing locale data</li> <li><a href="6f1171991a"><code>6f11719</code></a> fix(compiler): restrict possible event handler check to property names longer...</li> <li>Additional commits viewable in <a href="https://github.com/angular/angular/commits/v22.0.2/packages/core">compare view</a></li> </ul> </details> <br />
ng-flutter
This Angular project is a simple example of how Angular and Flutter web apps could be integrated, and have them interop.
Points of Interest
Angular
This repository is a quite standard Angular app. The following changes were made to be able to use (and interop) with a Flutter web application:
package.jsonhas a customprebuildscript that builds the Flutter web app, so Angular can find it later.flutter.jsis added as a"scripts"entry inangular.json. Angular takes care of minimizing and injecting it as any other script.- The rest of the flutter app
flutter/build/web/is registered as an"assets"entry inangular.json, and moved to/flutter. - The
ng-fluttercomponent takes care of embedding Flutter web, and yielding control to Angular through anappLoadedEventEmitter. The object yielded by this emitter is a state controller exposed by flutter via a JS custom event!
Flutter
The embedded Flutter application lives in the flutter directory of this repo.
That application is a standard web app, that doesn't need to be aware that it's
going to be embedded in another framework.
- Flutter uses new
@staticInteropmethods to allow certain Dart functions to be called from JavaScript. - Look at how
createDartExportandbroadcastAppEventwork together to make the_statecontroller of the Flutter app available to Angular!
How to build the app
Requirements
If you want to build and run this demo on your machine, you'll need a moderately recent version of Angular:
$ ng version
Angular CLI: 17.0.0
Node: 20.9.0
Package Manager: npm 10.1.0
OS: linux x64
And Flutter:
$ flutter --version
Flutter 3.13.9 • channel stable
Framework • revision d211f42860 (2 weeks ago) • 2023-10-25 13:42:25 -0700
Engine • revision 0545f8705d
Tools • Dart 3.1.5 • DevTools 2.25.0
Ensure npm, ng and flutter are present in your $PATH.
Building the app
This repository is a moderately standard Angular app. It integrates
Flutter web by making it part of the Angular assets.
In order to build this app, first fetch its npm dependencies:
$ npm install
added 963 packages, and audited 964 packages in 17s
93 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Then run the build script. It'll take care of building Flutter
automatically:
$ npm run build
> ng-flutter@0.0.0 prebuild
... Flutter web build output ...
Compiling lib/main.dart for the Web...
> ng-flutter@0.0.0 build
> ng build
... Angular build output ...
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.
Local Angular development
Once you've reached this point, you should be able to work with your Angular application normally, for example to run a local web server:
$ npm run start
> ng-flutter@0.0.0 start
> ng serve
✔ Browser application bundle generation complete.
Initial Chunk Files | Names | Raw Size
vendor.js | vendor | 4.38 MB |
... Angular build output...
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
✔ Compiled successfully.
Navigate to http://localhost:4200/. The application will automatically reload
if you change any of its Angular source files.
Local Flutter web development
The Flutter app lives inside the flutter directory, and can be
developed independently. Just do any changes on Flutter web as you'd
normally do. It even includes a small web/index.html so you can see
changes to your app without running the whole Angular setup.
Note
For now, Angular does not auto-detect changes to your Flutter web app, so once you're happy with your Flutter web app, make sure to call
npm run buildso everything rebuilds and gets placed into its correct location.
Deploying the app
After npm run build, you should have a deployable Angular + Flutter
web app in the dist directory of this Angular project.
Your built app can can be deployed anywhere, but do check Firebase hosting for a super-easy deployment experience!
Troubleshooting
Flutter
Ensure your flutter app is properly rebuilt after any changes.
- Run
npm run buildto re-build the Flutter app.
If you encounter error messages like:
Error: Can't resolve 'flutter/build/web/flutter.js' in '/my/checkout/of/ng-flutter'
You definitely need to run npm run build!
Reach out to the team(s)!
Have you had any problem not covered in this README? Do you want to see other embedding examples?
Let us know by creating an issue or opening a new pull request.
Thanks!