mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(elements): support output()-shaped outputs (#57535)
Previously Elements was assuming that every output was an RxJS `Subject` and supports `.pipe()`. This is not true for `output()`-based outputs which have `.subscribe()` but not `.pipe()`. This commit fixes such outputs by using a `new Observable` instead of `map` to forward outputs. PR Close #57535
This commit is contained in:
committed by
Andrew Kushnir
parent
3896f86865
commit
fe5c4e086a
@@ -18,9 +18,10 @@ import {
|
||||
ɵChangeDetectionScheduler as ChangeDetectionScheduler,
|
||||
ɵNotificationSource as NotificationSource,
|
||||
ɵViewRef as ViewRef,
|
||||
OutputRef,
|
||||
} from '@angular/core';
|
||||
import {merge, Observable, ReplaySubject} from 'rxjs';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
|
||||
import {
|
||||
NgElementStrategy,
|
||||
@@ -219,8 +220,11 @@ export class ComponentNgElementStrategy implements NgElementStrategy {
|
||||
protected initializeOutputs(componentRef: ComponentRef<any>): void {
|
||||
const eventEmitters: Observable<NgElementStrategyEvent>[] = this.componentFactory.outputs.map(
|
||||
({propName, templateName}) => {
|
||||
const emitter: EventEmitter<any> = componentRef.instance[propName];
|
||||
return emitter.pipe(map((value) => ({name: templateName, value})));
|
||||
const emitter: EventEmitter<any> | OutputRef<any> = componentRef.instance[propName];
|
||||
return new Observable((observer) => {
|
||||
const sub = emitter.subscribe((value) => observer.next({name: templateName, value}));
|
||||
return () => sub.unsubscribe();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
Input,
|
||||
NgZone,
|
||||
Output,
|
||||
OutputEmitterRef,
|
||||
SimpleChange,
|
||||
SimpleChanges,
|
||||
createComponent,
|
||||
@@ -113,6 +114,18 @@ describe('ComponentFactoryNgElementStrategy', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should listen to output() emitters', () => {
|
||||
const events: NgElementStrategyEvent[] = [];
|
||||
strategy.events.subscribe((e) => events.push(e));
|
||||
|
||||
componentRef.instance.output3.emit('output-a');
|
||||
componentRef.instance.output3.emit('output-b');
|
||||
expect(events).toEqual([
|
||||
{name: 'templateOutput3', value: 'output-a'},
|
||||
{name: 'templateOutput3', value: 'output-b'},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should initialize the component with initial values', () => {
|
||||
expect(strategy.getInputValue('fooFoo')).toBe('fooFoo-1');
|
||||
expect(componentRef.instance.fooFoo).toBe('fooFoo-1');
|
||||
@@ -369,6 +382,7 @@ export class CdTrackerDir {
|
||||
export class TestComponent {
|
||||
@Output('templateOutput1') output1 = new Subject();
|
||||
@Output('templateOutput2') output2 = new Subject();
|
||||
@Output('templateOutput3') output3 = new OutputEmitterRef();
|
||||
|
||||
@Input() fooFoo: unknown;
|
||||
@Input({alias: 'my-bar-bar'}) barBar: unknown;
|
||||
|
||||
Reference in New Issue
Block a user