mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
The custom element implementation previously used a custom code path for setting inputs, which contained bespoke code for writing input properties, detecting whether inputs actually change, marking the component dirty, scheduling and running CD, invoking `ngOnChanges`, etc. This custom logic had several downsides: * Its behavior different from how Angular components behave in a normal template. For example, inputs setters were invoked in `NgZone.run`, which (when called from outside the zone) would trigger synchronous CD in the component, _without_ calling `ngOnChanges`. Only when the custom rAF- scheduled `detectChanges()` call triggered would `ngOnChanges` be called. * CD always ran multiple times, because of the above. `NgZone.run` would trigger CD, and then separately the scheduler would trigger CD. * Signal inputs were not supported, since inputs were set via direct property writes. This change refactors the custom element implementation with two changes: 1. `ComponentRef.setInput` is used instead of a custom code path for writing inputs. This allows us to drop all the custom logic related to managing `ngOnChanges`, since `setInput` does that under the hood. `ngOnChanges` behavior now matches how the component would behave when _not_ rendered as a custom element. 2. The custom rAF-based CD scheduler is removed in favor of the main Angular scheduler, which now handles custom elements as necessary. Running `NgZone.run` is sufficient to trigger CD when zones are used, and the hybrid zoneless scheduler now ensures CD is scheduled when `setInput` is called even with no ZoneJS enabled. As a result, the dedicated elements scheduler is now only used when Angular's built-in scheduler is disabled. As a concession to backwards compatibility, the element's view is also marked for refresh when an input changes. Doing this allows CD to revisit the element even if it becomes dirty during CD, mimicking how it would be detected by the former elements scheduler unconditionally refreshing the view a second time. As a part of this change, the elements tests have been significantly refactored. Previously all of Angular was faked/spied, which had a number of downsides. For example, there were tests which asserted that change detection only happens once when setting multiple inputs. This wasn't actually the case (because of `NgZone.run` - see logic above) but the test didn't catch the issue because it was only spying on `detectChanges()` which isn't called from `ApplicationRef.tick()`. Even the components were fake. Now, the tests use real Angular components and factories. They've also been updated to not use `fakeAsync`. A number of tests have been disabled, which were previously asserting behavior that wasn't matching what was actually happening (as above). Other tests were disabled due to real differences with `ngOnChanges` behavior, where the current behavior could be seen as a bug. Fixes #53981 BREAKING CHANGE: as part of switching away from custom CD behavior to the hybrid scheduler, timing of change detection around custom elements has changed subtly. These changes make elements more efficient, but can cause tests which encoded assumptions about how or when elements would be checked to require updating. PR Close #56728 |
||
|---|---|---|
| .. | ||
| src | ||
| test | ||
| BUILD.bazel | ||
| index.ts | ||
| package.json | ||
| PACKAGE.md | ||
| public_api.ts | ||