As described in
https://github.com/angular/angular/discussions/49681#discussioncomment-5628930,
if an `Observable` created from a signal with `toObservable` is
subscribed to in a template, it will initially have `null` as the value.
Immediately after the template is done executing, effects are flushed
and this results in the `AsyncPipe` getting a new value before the
`checkNoChanges` pass, resulting in `ExpressionChanged` error.
```
template: '{{obs$ | async}}'
...
obs$ = toObservable(signal(0));
```
Instead, this commit updates the `toObservable` to synchronously emit
the initial value to the Observable stream.
Side note here: We don't exactly encourage this pattern. Instead of
using `AsyncPipe`, the template should just read signals.
PR Close#49894
saying that providers of this NgModule is available to components,pipes and directive of "this" ngModule is not accurate sentence to describe the fact.
I am referring from: https://angular.io/guide/hierarchical-dependency-injection.
It says that "ModuleInjector is configured by the @NgModule.providers and NgModule.imports property. ModuleInjector is a flattening of all the providers arrays that can be reached by following the NgModule.imports recursively."
So, any component,pipe or directive of other NgModule within same ModuleInjector can use providers of this NgModule.
PR Close#49966
Hydration relies on a signal from ZoneJS when it becomes stable inside an application, so that Angular can start serialization process on the server or post-hydration cleanup on the client (to remove DOM nodes that remained unclaimed).
Providing a custom or a "noop" ZoneJS implementation may lead to a different timing of the "stable" event, thus triggering the serialization or the cleanup too early or too late. This is not yet a fully supported configuration.
This commit adds a warning (non-blocking) for those cases.
PR Close#49944
In this mode the compiler generates code based on each individual source file without using its dependencies. This mode is suitable only for fast edit/refresh during development.
PR Close#49846
This commit updates hydration logic to hanlde a case when the same component is used multiple times in a template and in some of those cases, component is opted-out of hydration, for example:
```
<cmp ngSkipHydration />
<cmp />
```
Previously, the first occurrence of the `<cmp>` would result in storing the `ssrId` on a TView as `null` (since hydration is disabled for the component) and the second component instance reused the `null` as a value, thus also skipping hydration.
With the changes from this commit, the `ssrId` would be set when we come across a hydratable instance. We also make sure that the `ssrId` value never changes after we first set it to a non-`null` value.
PR Close#49943
This change explicitly resets a reactive consumer before setting inputs
on directive instances. This is to assure that any potential input setters
do _not_ run in the reactive context.
PR Close#49906
When binding an array to `class` like `[class]="['foo', 'bar']"`, the runtime treats it the same as a literal binding with all the values being `true`, e.g. `{foo: true, bar: true}`. While object literals can only have string keys, arrays can have any value which can lead to errors if the array contains non-string values.
These changes add some logic to stringify the keys and ignore invalid ones.
Fixes#48473.
PR Close#49924
This commits update the platform-server test structure to add 2 applications in the Angular CLI workspace one based on ngmodules and another standalone. The same E2E suit is ran on both apps.
PR Close#49927
This commit updates hydration logic to handle cases when there are projection slots present in a template inside of an `<ng-container>` and when there are regular elements follow an <ng-content> slot (see tests for additional information). With this combination, the logic that annotates regular element locations should fallback to calculating a path from a reference node to that node. In case of an <ng-container>, the comment node is located *after* the node that needs an annotation. An existing logic was mistakenly returning an empty path, which was represented as a pointer to teh reference node. This commit fixes that and triggers a fallback to using a component host node as a reference in this case.
Resolves#49918.
PR Close#49920