I have one suggestion for you guys for using Observable for Output in Angular. I thought you might not know about that because it wasn’t get mentioned in the documentation. Take a look at the below code and and I will explain on the later part.
@Output() someEvent = new EventEmitter();
this.someSource$.pipe(
/* additional logic transformation */
).subscribe(data => this.someEvent.emit(data));@Output() someEvent = this.someSource$.pipe(
/* additional logic transformation */
);As you can see, the before and after code was pretty much identical. Its use-case is applicable when you want to use Output to emit something for the Parent Component when someSource$ emit data. But why it works?
To go a bit deeper, you need to understand two things:
(eventName)EventEmitterEvent binding is what you see when using a parenthesis and a event name on the template part, e.g. <child (someEvent)="invokeSomeEvent()"></child>.
Basically, Angular Compiler will parse all the template to Abstract Syntax Tree (AST) so that I can have all information regarding the current template. For the event binding, Angular knows which event get binding on the template itself.
If you look at source code of output_interpreter, there is one path to check if the current event is SubscribeObservable, it will automatically subscribe to that Observable.
What does this mean? If event is either Observable/Subject, Event Binding syntax () will automatically do the subscribe.
EventEmitter is a subclass of Subject under the hood. And as you might have already known, Subject acts as both Observable and Observer. With the code on the above output_interpreter, if you change an EvenEmitter with a Subject/Observable, it will be automatically subscribed.
When you understand the two concepts Event Binding syntax and EventEmitter, I hope you get why the above code works.
Angular team also use this approach for one of their search-box component example. Thanks chandlerfang for the input!
View the source code
@Component({
selector: 'aio-search-box',
template: `
<input
#searchBox
type="search"
aria-label="search"
placeholder="Search"
(keyup)="doSearch()"
/>
`,
})
export class SearchBoxComponent implements AfterViewInit {
private searchDebounce = 300
private searchSubject = new Subject<string>()
@Output() onSearch = this.searchSubject.pipe(
distinctUntilChanged(),
debounceTime(this.searchDebounce)
)
doSearch() {
this.searchSubject.next(this.query)
}
}Have fun!
Thanks Chau Tran for the original Vietnamese version.