2016-08-25 127 views
1

我认为有一个简单的问题,但我有一个很难找到的确认,如果我的解决办法是“正确的”订阅子组件的可观察(valueChanges)

我有一个孩子组件SearchComponentformControl

@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(); 
    } 

} 

我在父组件模板使用此

<div class="col-md-2 sidebar"> 
    <my-search [placeholder]="'search'"></my-search> 
</div> 

我现在想订阅searchValues可从父母内部观察。最好的我想出的是:

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 

} 

这是推荐的方法?有没有更好的方法来定义组件之间的合同(如可以使用@Input@Output)?

回答

2

您可以轻松使用@Output。 在搜索组件,你可以添加一个像:

@Output() searchEvent: EventEmitter = new EventEmitter(); 

然后订阅文本的变化和(重新)发出他们:

this.search.valueChanges 
     .debounceTime(400) 
     .distinctUntilChanged() 
     .subscribe((event) => this.searchEvent.emit(event)); 

之后,你已经输出,你可以在任何使用父组件。不需要任何组件引用(ViewChild)。使用这将是在你推变化updateStream = new Subject()和事件处理程序(searchEvent) = "updateStream.next($event)"父组件一个主题

编辑

的一种方式。

然后,您可以创建可观察到这样的:

foo = updateStream.flatMap((s) => myService.find(s)) 
+0

由于这是有道理的,但是它不公开的'Observable',其然后可以进一步为例如由父处理(!)。然而,我喜欢这种简单性,但另一方面会喜欢看到observables作为契约而不是'EventEmitter' – jen

+0

它实际上扩展了Subject类型,因为它可以[发出和订阅](https:// angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html)。在父组件中,您可以拥有一个Observable/Subject,您可以将事件更改推送到合并/映射到您需要的位置。 –

+0

感谢您的评论和额外的编辑。这工作完美并且“干净”。我想知道他们是否会更容易订阅一个'@ output''Source',比如'EventEmitter'(但是老实说,不知道应该看起来像什么)。再次感谢你的帮助 :) – jen