Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6 Data Sharing Service Subscribe not triggered

I need to set Value in One Component (Component A) and Receive the Value in another Component (Component B). Component A and Component B are not Parent and Child.

I created a Shared Service to Share data between the 2 components. I'm able to set the value from Component B, but when I Subscribe to get the value in Component A, it's not being triggered.

Here is what I have tried:

I added Service in @NgModule providers array in appmodule.ts file so that it is available for all the components in the project.

Service Code:

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from '../../node_modules/rxjs';

@Injectable({
  providedIn: 'root'
})
export class SocialService {

  constructor() { }

  private valueObs: BehaviorSubject<string> = new BehaviorSubject<string>(null);

 public setValue(value: string):void {
     this.valueObs.next(value);
     this.getValue();
 }

 public getValue():Observable<string> {
     return this.valueObs;

 }

}

Component B: Setting value here

@Component({
  selector: 'app-componentb',
  templateUrl: './componentb.component.html',
  styleUrls: ['./componentb.component.scss']
})


constructor(private socialService: SocialService, private http: HttpClient) {



}

 buttonClick()
 {

    this.socialService.setValue("linked successfully");
 }

Component A: Get Value Here

@Component({
  selector: 'app-componenta',
  templateUrl: './componenta.component.html',
  styleUrls: ['./componenta.component.scss']
})


constructor(private socialService: SocialService, private http: HttpClient) {

       this.socialService.getValue().subscribe(data=>{

    console.log('Trigger from ComponentB');
    console.log(data);

});

}

Trigger in ComponentA is being called when ComponentA is loaded with data being null. But it is not getting called when buttonClick is called from ComponentB.

UPDATE:

I figured out the problem, I should have phrased my question properly. When ComponentA and ComponentB are in the same Page(URL), the code works perfectly.

How do I send data between 2 components when they are in 2 different pages(URLS).

Example: User opens URL1 (Renders ComponentA) which has a button, User clicks on the Button and is redirected to URL2 (Renders ComponentB) in a new tab which has a button, when User clicks on the button, I need to pass some data to ComponentA and close URL2. I need to retrieve the data passed in ComponentB and use it in URL1. Is it possible using Services? If not, which approach should I follow?

like image 790
Anirudh Avatar asked Feb 18 '19 07:02

Anirudh


2 Answers

You could effectively use Subject along with the router. So, Here is a live solution for your scenario using Router & Subject.

Your service will simply contain -

public setValue(value: string): void {
    this.valueObs.next(value);
}

public getValue(): Observable < string > {
    return this.valueObs;
}

Then, your ComponentB will contain -

buttonClick() {
    this.socialService.setValue("linked successfully");
    this.router.navigate(['/a']);
}

And, your ComponentA's constructor will contain -

this.socialService.getValue().subscribe(data => {
    this.dataFromB = data;
    console.log('Trigger from ComponentB');
    console.log(data);
})
like image 83
Tushar Walzade Avatar answered Nov 13 '22 16:11

Tushar Walzade


I think you would need a ReplaySubject for that. Your component subscribing to the observable subscribes, after the value was emitted and hence the observable doesn't emit again, there is no value to get from that observable. A ReplaySubject takes care of giving the subscriber every emits which have taken place even before the subscription is done.

@Tushar Walzade solution works, because both components are within the app-component, so both observers are subscribing before the event was emitted. (The subscription takes place inside the constructor for both components, which is called before you click the button). But if you have a lazy loaded module for example, the one component would be created only on loading and then you would only get the data if you use a ReplaySubject or the rxjs operator publish or share

Have a look here:

publish and share operators subjects, behavior subjects and replay subjects

like image 20
Erbsenkoenig Avatar answered Nov 13 '22 17:11

Erbsenkoenig