【问题标题】:I want to send an observable up 2 parent components. How would I do this? Would I need to use an EventEmitter?我想发送一个可观察的 2 个父组件。我该怎么做?我需要使用 EventEmitter 吗?
【发布时间】:2019-10-01 20:38:32
【问题描述】:

我有一个页面组件、一个列表组件和一个详细信息组件(父级到子级层次结构:page->list->detail),我试图通过组件在详细信息组件中获取一个可观察到的页面组件分享。

我尝试通过将 observable 放入 EventEmitter 并将其向上发送来做到这一点,但是,它似乎不起作用。它可能是以下两种情况之一:我错误地发送了 observable,或者我正确地发送了 observable 并且我错误地从 EventEmitter 中提取了它。代码看起来像这样。

详细组件:

@Output() outputHumidityWarning$ = new EventEmitter<Observable<boolean>>();
...
ngOnInit() {
  this.outputHumidityWarning$.emit(this.humidityWarning$);
}

湿度警告$ 的类型为 Observable

列表组件模板:

<app-detail (outputHumidityWarning$)="inputHumidityWarning($event)"</app-detail>

列表组件:

private humidityWarning = new Replaysubject<boolean>(1);
...
ngOnInit() {
  this.humiditywarning.subscribe(all => console.log(all));
}
...
inputHumidityWarning = function (humidityWarning) {
  this.humidityWarning = humidityWarning;
}

我也试过了:

inputHumidityWarning = function (humidityWarning) {
  this.humidityWarning.next(humidityWarning);
}
...
inputHumidityWarning = function (humidityWarning) {
  this.humidityWarning.next(of(humidityWarning));
}

没有错误,但我不会在控制台上得到任何东西。 当我在设置后 console.log this.humidityWarning 时,我会得到一个 AnonymousSubject。这就是为什么我尝试将其包装为 of()。 当我 console.log(humanityWarning) 我会得到一个 EventEmitter

【问题讨论】:

  • 如果我的解决方案不能解决您的问题,请告诉我删除我的答案,如果您可以为其提供 stackblitz 链接,人们可以更好地帮助您

标签: angular angular2-observables eventemitter


【解决方案1】:

我可能误解了您的目标,但我以不同的方式完成了类似的组件通信。例如,考虑可能需要在多个组件之间共享的应用程序状态。

我通常创建一个服务,该服务公开一个 observable 并将 Behavior Subject 实现为观察者和 observable。然后我可以将服务注入到像你的子组件这样的组件中作为输入,并在其他需要观察的组件中订阅服务,比如你的父组件。我通常使用接口在服务中定义具有已定义类型的 observable 来保留它。

这是我创建的一个示例,用于管理由各种组件更新的搜索参数。

服务:

import { Injectable } from '@angular/core'
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { SearchParams, Filter } from '../components/searchParam/searchparams.entity';
import { ISearchParams } from '../components/searchParam/searchparams.interface';
import { parkDetails } from '../services/getParkDetails.service';


@Injectable()
export class searchParamStateService {
    private _searchParamSource: BehaviorSubject<ISearchParams>;
    searchParams: Observable<ISearchParams>;
    private dataStore: ISearchParams;

    constructor() {    
        this.dataStore = new SearchParams('', [],[],[]);
        this._searchParamSource = new BehaviorSubject<ISearchParams>(this.dataStore);
        this.searchParams = this._searchParamSource.asObservable();        
    }


    // called when the searchtextbox is updated in search component
    changeSearchString(searchString: string) {
        this.dataStore.SearchString = searchString;
        this._searchParamSource.next(Object.assign({}, this.dataStore));
    }


    setXYParams(lat, long) {  
        //console.log('searchparamstate.service setXYParams: ' + lat + '  ' + long);
        this.dataStore.SearchX = lat;
        this.dataStore.SearchY = long;
        this._searchParamSource.next(Object.assign({}, this.dataStore));

    }

}

然后在组件中我可以观察或贡献状态:

//inject service into component

...

searchstateService.data.subscribe(data => {
  //do what ever needs doing when data changes
})

...

//update the value of data in the service
searchstateService.changeSearchString('new search string);

【讨论】:

  • 是的,我考虑过为此使用服务。无论如何,是否可以将任意数量的 observable 从 detail 组件发送到服务,然后返回到父(列表)组件,而 observable 不会相互覆盖?
  • 你能给我一个期望行为的例子吗?您所指的所有可观察对象都属于同一类型吗?我想象一个包含多个细节组件的父组件(列表)。列表中的每个细节项都需要向父母发出湿度警告?然后呢?我问是因为我认为您不需要发送“任意数量的 observables”。这似乎令人费解。
  • 记住 observables 可以传递任何类型的多个值。例如,您可以公开一个由可变长度的湿度警告列表组成的 observable,例如 -湿度警告:Observable>;
  • 还要记住,角度是反应性的,主体会发出事件流,这些事件流基本上由一系列随时间变化的值组成。流由曾经存在的主题的每个状态组成。这意味着如果您重置主题的属性,它不会完全覆盖该值,它会创建一个新状态以添加到序列中,如果您只需要知道所有发出的警告,您可以利用主题的反应性质重播警告。
  • subject.asObservable 创建了一个可以添加到事件流中并且订阅者也可以观察到的主题。这是关于该主题的一个很好的资源:@​​987654321@
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-31
  • 1970-01-01
  • 2023-04-06
相关资源
最近更新 更多