1
votes

I have a page component, a list component and a detail component (parent to child hierarchy: page->list->detail) and I'm trying to get an observable in the detail component up to the page component through component sharing.

I've tried doing this by putting the observable in an EventEmitter and sending it upward, however, it doesn't seem to be working. It could be one of two things: I'm incorrectly sending the observable up, or I'm correctly sending the observable up and I'm incorrectly extracting it from the EventEmitter. The code looks something like this.

Detail component:

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

Where humidityWarning$ is of type Observable

List component template:

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

List component:

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

I've also tried:

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

No errors but I won't get anything on the console. When I console.log this.humidityWarning after setting it, I'll get an AnonymousSubject. This is why I tried wrapping it an of(). When I console.log(humidityWarning) I'll get an EventEmitter

1
If my solution doesn't solve your issue let me know to delete my answer, as well as if you can provide stackblitz link for it, people can help you betterReza

1 Answers

1
votes

I may be misunderstanding your objective, but I have accomplished similar component communication a different way. For example consider application state that may need to be shared among multiple components.

I typically create a service that exposes an observable and implements Behavior Subject as both an observer and observable. Then I can inject the service into the into components like your child component as an input and subscribe to the service in other components that need to observe, like your parent component. I usually define the observable in the services with a defined type using an interface to keep it.

Here is an example I created to manage search parameters that were updated by various components.

The service:

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));

    }

}

Then in components I can observe or contribute to the state:

//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);