Reputation: 357
I thought to have a simple problem, but i am having a hard time finding confirmation if my solution is "correct"
I have a child component SearchComponent
with a formControl
@Component({
selector : "my-search",
inputs : ["placeholder"],
template : `
<div class="searchForm">
<input type="text" [placeholder]="placeholder" [formControl]="search"/>
</div>
`
})
export class SearchComponent {
search = new FormControl();
public searchValues : Observable<string>;
constructor() {
this.searchValues = this.search.valueChanges
.debounceTime(400)
.distinctUntilChanged();
}
}
I am using this in the parent component's template
<div class="col-md-2 sidebar">
<my-search [placeholder]="'search'"></my-search>
</div>
I now want to subscribe to the searchValues
Observable from within the parent. The best i came up with is:
export class MyListComponent implements AfterContentInit {
@ViewChild(SearchComponent) searchComponent: SearchComponent;
constructor(private myService: MyService ) {
}
ngAfterContentInit() {
this.searchComponent.searchValues.subscribe(s=>this.search(s))
}
private search(s: string) {
this.foos = this.myService.find(s);
}
foos: Observable<[Foo]>; // used on a ngFor | async
}
Is this recommended approach? Is there no better way to define the contract between the components (like can be done with @Input
and @Output
)?
Upvotes: 2
Views: 10141
Reputation: 12572
You could easily use @Output for this. In the search component you could add one like:
@Output() searchEvent: EventEmitter = new EventEmitter();
Then subscribe to the text changes and (re)emit them:
this.search.valueChanges
.debounceTime(400)
.distinctUntilChanged()
.subscribe((event) => this.searchEvent.emit(event));
After that you have the Output that you can use in any parent component. Without any need for a component reference (ViewChild).
Edit
One way to use this would be to have a Subject in the parent component that you push changes to updateStream = new Subject()
and the event handler (searchEvent) = "updateStream.next($event)"
.
Then you can create the Observable like:
foo = updateStream.flatMap((s) => myService.find(s))
Upvotes: 3