我正在构建一个Angular 2应用程序,其搜索表单和结果显示在同一页面上。我使用路由来显示结果部分。所以父组件是具有多个字段的搜索表单,子组件从后端获得结果并显示它。
由于搜索条件涉及多个字段,因此我通过共享服务将搜索条件传递给子组件。
父组件:
@Component({
templateUrl : 'app/search-form.template.html'
})
export class SearchFormComponent {
constructor(private searchService : SearchService,
private router: Router){}
submitSearch(){
this.searchService.setSearchCriteria(this.model);
this.router.navigate(['search-form/search-result']);
}
子组件:
@Component({
templateUrl: 'app/search-result/search-result.template.html'
})
export class SearchResultComponent implements OnInit{
private searchResult = [] ;
constructor(private searchService: SearchService) { }
ngOnInit() {
this.searchService.getSearchResult().subscribe(data => {
this.searchResult = data;
});
}
这是服务代码:
@Injectable()
export class SearchService{
constructor (private http: Http) {}
setSearchCriteria(searchCriteria : SearchCriteria){
this.searchCriteria = searchCriteria;
}
getSearchResult() : Observable<any> {
let body = JSON.stringify(this.searchCriteria);
let headers = new Headers({'content-type' : 'application/json'});
let options = new RequestOptions({headers : headers});
return this.http.post(this.baseUrl , body, options)
.map((res: Response) => res.json().root || {});
}
使用路由加载父级和子级。这是路由详细信息
const appRoutes : Routes = [
{
path: '',
redirectTo: '/search-form',
pathMatch: 'full'
},
{
path: 'search-form', component: SearchFormComponent,
children: [
{ path: ''},
{ path: 'search-result', component: SearchResultComponent }
]
}
];
main.html看起来像这样。这里搜索表单(父级)呈现为“搜索表单”
<nav class="navbar" >
<div class="container-fluid">
<router-outlet></router-outlet>
</div>
</nav>
search-form.template.html代码段
<nav class="navbar" >
<div class="container-fluid">
<router-outlet></router-outlet>
</div>
</nav>
在父表单提交时调用parent的submitSearch()方法。它导航到子组件并显示searchResult。直到现在它工作正常。
我想要的是用户应该能够在屏幕上更改搜索条件并再次点击提交按钮。调用submitSearch()方法,但不更新子组件的结果。我认为根本原因是因为子组件在ngOnInit方法中调用服务。显示结果后,当我在同一页面上时,重新按下提交按钮不会再次创建子组件,因此数据不会刷新。
如何在父组件提交时使用新的searchResult重新加载子项。
答案 0 :(得分:1)
目前还不清楚你是如何进行这种连接的。您说SearchResultComponent
是SearchFormComponent
的孩子,但您在运行setSearchCriteria
之后导航到它,就像它自己的组件在哪里一样。由于我们无法看到模板,因此很难理解正在发生的事情。
我通常会这样做的方法是在getSearchResult()
之后在父级中运行setSearchCriteria()
并将结果传递给@Input
中的孩子。如果您使用ActivatedRoute服务之类的东西导航父级,则将子代码从ngOnInit
移动到ngOnChanges
,以便在输入更改时刷新。
答案 1 :(得分:1)
Subject
内应该SearchService
。称之为currentResult
。一个主题就像一个双向可观察者,它既是生产者又是消费者。因此,在父端,您可以成为生产者,而子项结束消费者。
您可能不想在onInit中设置搜索条件,但在父级中发生某些操作时。然后,您可以为孩子生成一些值,这将是正在收听的。
也许是这样的
从&#39; rxjs / Subject;
导入{Subject}@Injectable()
class SearchService {
private currentSearch = new Subject<any>();
searchAndSetCurrent(criteria) {
this.http.get(..).toPromise().then(result => {
currentSearch.next(result);
});
}
getCurrentSearch(): Observable<any> {
// asObservable is not really necessary as you can subscribe
// to a subject. But to make sure people calling this method
// don't try to emit anything, we should just limit it
// to the capabilities of an Observable
return this.currentSearch.asObservable();
}
}
现在父母可以打电话给searchAndSetCurrent
,孩子可以订阅。无论何时父母调用搜索,当结果出现时,孩子都会得到它。
如果您想对父项中的结果执行某些操作,可以使搜索方法返回一个承诺
searchAndSetCurrent(criteria)L Promise<any> {
return this.http.get(..).toPromise().then(result => {
currentSearch.next(result);
return this;
});
}
有关Subject
的更多信息,您可以check this out