0
votes

I have declared a subject in service and tried to push the response got by making a GET call to back end using "subject.next()"..also assigned an observable for the subject using "subject.asObservable()" and subscribed to the observable in two different components(parent and router outlet child). Problem is that the observable is emitting the new value for only one subscriber not for two subscribers.

Service

  subject = new Subject<any>();
  observable = this.subject.asObservable();


 public getDetails(id) {
    return this.http.get(this.url.concat(id))
      .pipe(map(data => this.extractDetails(data),
            catchError(err => this.handleError(err)));
  }
 public extractDetails(data){
    this.subject.next(data);
    return data;
  }

parent component

ngOnInIt(){
 this.hitUrl();

}
getDetails(){
    this.service.observable.subscribe(
      (data: any) => {
        console.log(data);
      },
      err => {
        console.error(err);
      }
    )
  }

  hitUrl(id: string) {
    this.service.getDetails(id).subscribe(
      (data: any) => 
        if(!!data){
            console.log(data);
            this.getDetails();
          }
      },
      err => {
        console.log(err);
      }
    );
  }

router-outlet child component

ngOnInIt(){
 this.hitUrl();

}
getDetails(){
    this.service.observable.subscribe(
      (data: any) => {
        console.log(data);
      },
      err => {
        console.error(err);
      }
    )
  }

  hitUrl(id: string) {
    this.service.getDetails(id).subscribe(
      (data: any) => 
        if(!!data){
            console.log(data);
            this.getDetails();
          }
      },ngOnInIt(){
 this.hitUrl();

}
getDetails(){
    this.service.observable.subscribe(
      (data: any) => {
        console.log(data);
      },
      err => {
        console.error(err);
      }
    )
  }

  hitUrl(id: string) {
    this.service.getDetails(id).subscribe(
      (data: any) => 
        if(!!data){
            console.log(data);
            this.getDetails();
          }
      },
      err => {
        console.log(err);
      }
    );
  }

      err => {
        console.log(err);
      }
    );
  }


In the components hitUrl() also triggers when a call to action is performed then i need that observable should emit latest data to both the subscribers(if call to action is performed from parent or router outlet child).

1
Why do you even need a subject in your case? you can directly subscribe to the http request in both of your components. - Ramesh Reddy
both the call to actions are in one page(web view)..if one of it is called then other should also gets updated("Follow" should change to "Following").. - Ganesh
place getDetails() call in each of ngOnInits. that is how your components would subscribe to observables - Andrei
Try the 'tap' method instead of the map in the service. We use map when we want to change data. - József Cserkó
called getDetails() in both components ngOnInits... - Ganesh

1 Answers

0
votes

what i understood from your question is that you have two components and a service you are getting data using service and want to send the data to both components at the same time when ever the following 'getDetails()' function is called regardless of where this function is being called from. it could be parent calling the function or the child.

 public getDetails(id) {
     return this.http.get(this.url.concat(id))
       .pipe(map(data => this.extractDetails(data),
             catchError(err => this.handleError(err)));   }

In your code the problem is with the components code you are calling the getDetails function and the inside that function you are subscribing the observable instead you should be subscribing the observable in ngOnInit. so that when ever this observable.next is called from service the observable will execute in both components because it will be subscribed over there see the code below.

 ngOnInit(){
     this.getDetails();
     this.hitUrl();   }

 getDetails(){
   this.service.observable.subscribe(
     (data: any) => {
       console.log(data);
     },
     err => {
       console.error(err);
     }
   )   
 }

 hitUrl(id: string) {
   this.service.getDetails(id).subscribe(
     (data: any) => 
       if(!!data){
           console.log(data);
         }
     },
     err => {
       console.log(err);
     }
     );   
 }

In above code first we are subscribing the subject and then we are calling the data. inside the getDetails(id) function in service we are already emmiting the subject and also replace the following line in service.

subject = new Subject<any>();
  observable = this.subject.asObservable();

with the following

subject = new BehaviorSubject({});

hope this helps...