fix(elements): fire custom element output events during component initialization (#36161)

Previously, event listeners for component output events attached on an
Angular custom element before inserting it into the DOM (i.e. before
instantiating the underlying component) didn't fire for events emitted
during initialization lifecycle hooks, such as `ngAfterContentInit`,
`ngAfterViewInit`, `ngOnChanges` (initial call) and `ngOnInit`.
The reason was that that `NgElementImpl` [subscribed to events][1]
_after_ calling [ngElementStrategy#connect()][2], which is where the
[initial change detection][3] takes place (running the initialization
lifecycle hooks).

This commit fixes this by:
1. Ensuring `ComponentNgElementStrategy#events` is defined and available
   for subscribing to, even before instantiating the component.
2. Ensuring `NgElementImpl` subscribes to `NgElementStrategy#events`
   before calling `NgElementStrategy#connect()` (which initializes the
   component instance).

Jira issue: [FW-2010](https://angular-team.atlassian.net/browse/FW-2010)

[1]: c0143cb2ab/packages/elements/src/create-custom-element.ts (L167-L170)
[2]: c0143cb2ab/packages/elements/src/create-custom-element.ts (L164)
[3]: c0143cb2ab/packages/elements/src/component-factory-strategy.ts (L158)

Fixes #36141

PR Close #36161
This commit is contained in:
George Kalpakas
2020-06-05 20:14:18 +03:00
committed by atscott
parent 411cb0cb92
commit e9bff5fe9f
4 changed files with 52 additions and 11 deletions

View File

@ -117,6 +117,16 @@ if (browserDetection.supportsCustomElements) {
expect(eventValue).toEqual(null);
});
it('should listen to output events during initialization', () => {
const events: string[] = [];
const element = new NgElementCtor(injector);
element.addEventListener('strategy-event', evt => events.push((evt as CustomEvent).detail));
element.connectedCallback();
expect(events).toEqual(['connect']);
});
it('should properly set getters/setters on the element', () => {
const element = new NgElementCtor(injector);
element.fooFoo = 'foo-foo-value';
@ -255,6 +265,7 @@ if (browserDetection.supportsCustomElements) {
events = new Subject<NgElementStrategyEvent>();
connect(element: HTMLElement): void {
this.events.next({name: 'strategy-event', value: 'connect'});
this.connectedElement = element;
}