7

I wanted to send data using subject to another component (for a earning purpose). I am not able to fetch back the data. Here is my code:

app.component.ts

import { Component } from '@angular/core';
import { shareService } from './share.service';

@Component({
 selector: 'my-app',
  template: `
  <hello></hello>
  <button (click)="passData()">
    Start
  </button>
  `,
  styleUrls: [ './app.component.css' ],
  providers:[shareService]
})
export class AppComponent  {
  constructor(private service : shareService){}

  passData(){
   this.service.send("hello");
}

}

hello.component.ts

import { Component, Input } from '@angular/core';
import { shareService } from './share.service';
import { Subscription }   from 'rxjs/Subscription';

@Component({
  selector: 'hello',
  template: `<h1>Hello!</h1>`,
  styles: [`h1 { font-family: Lato; }`],
  providers:[shareService]
})
export class HelloComponent  {
  subscription: Subscription;
    constructor(private share : shareService){
    this.subscription =  share.subj$.subscribe(val=>{
    console.log(val);
    })
  }
}

share.service.ts

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';

@Injectable()
export class shareService{

  private sub = new Subject();
  subj$ = this.sub.asObservable();

    send(value: string) {
    this.sub.next(value);
  }

}

I am not getting the value in console.

Here is the working Demo : DEMO

Vega
  • 27,856
  • 27
  • 95
  • 103
Sampath1504
  • 131
  • 1
  • 13
  • 1
    if you want to go deep and see how data can be shared between modules this will interest you https://stackoverflow.com/questions/40089316/how-to-share-service-between-two-modules-ngmodule-in-angular2 – Aniruddha Das Aug 31 '17 at 18:34

2 Answers2

8

By putting:

@Component({
  .....
  providers: [sharedService]
})

in both components, you are creating two distinct instances of the shared service. Each instance is not 'aware' of the data from each component. Provide it at module level and create a singleton service:

@NgModule({
  ....
  providers: [sharedService]
})

This way, you inject the service as a single instance in the both components, so they can share it as they will share the data.

Or using the Angular's preferred new way :

Beginning with Angular 6.0, the preferred way to create a singleton service is to specify on the service that it should be provided in the application root. This is done by setting providedIn to root on the service's @Injectable decorator:

@Injectable({
  providedIn: 'root',
})

Demo

See also

Vega
  • 27,856
  • 27
  • 95
  • 103
  • But should'nt it work if i provide it in each component separately? – Sampath1504 Aug 31 '17 at 18:38
  • https://stackblitz.com/edit/add-remove-components . Here is the demo of it . I have a close button on each element , if close it , my component is getting deleted , but why i am not able to add the same component again ?EG : If i close component 1 and try to add it again it's not working . Where am i making a mistake – Sampath1504 Sep 10 '17 at 11:52
  • From quick reading, it seems to me that when you destroy the parent component and shared service are not notified of the change – Vega Sep 10 '17 at 12:01
  • when i close it , ngOnChange is not getting fired . Is this the reason ? – Sampath1504 Sep 10 '17 at 12:08
  • What should i do it to change ? – Sampath1504 Sep 10 '17 at 12:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/154065/discussion-between-sampath1504-and-vega). – Sampath1504 Sep 10 '17 at 12:13
0

I dont know why sub$ is used but you dont need that

// just push data to subject. you can use BehavourSubject to initiatte a value.
@Injectable()
export class shareService{

  private sub = new Subject();

    confirmMission(astronaut: string) {
    this.sub.next(astronaut);
  }

}

And then in your 2nd component sub scribe it

@Component({
  selector: 'hello',
  template: `<h1>Hello!</h1>`,
  styles: [`h1 { font-family: Lato; }`],
  providers:[shareService]  // this can be shared in module lebel or componenet level
})
export class HelloComponent  {
  subscription: Subscription;
    constructor(private share : shareService){
    this.subscription =  share.subj.subscribe(val=>{
    console.log(val);
    })
  }
} 

make sure to provide your service in module level or provide it in both the component.

Aniruddha Das
  • 20,520
  • 23
  • 96
  • 132
  • https://stackoverflow.com/questions/36986548/when-to-use-asobservable-in-rxjs is a good practice to expose an internal subject only through the observable interface – Jota.Toledo Aug 31 '17 at 18:35
  • So using asObservable is good right? – Sampath1504 Aug 31 '17 at 18:41
  • I never used that. The way I explaned I alwasy use it. for me its extra line of code and need to whrite and maitnain – Aniruddha Das Aug 31 '17 at 18:45
  • 2
    @Sampath1504 its about hidding the internal implementation of your shared service and the observer behavior of the subject, when your component (client) only cares about the observable behavior of it – Jota.Toledo Aug 31 '17 at 19:12
  • @Jota.Toledo and Aniruddha Das . Can you help me with this . This is my demo https://stackblitz.com/edit/add-remove-components . I have a close button on each element , if close it , my component is getting deleted , but why i am not able to add the same component again ?EG : If i close component 1 and try to add it again it's not working – Sampath1504 Sep 10 '17 at 13:10
  • https://stackoverflow.com/questions/46141132/angular-2-ngonchange-not-firing-on-deletion-of-component?noredirect=1#comment79244765_46141132 . Here is my question . I dont know where i am making a mistake – Sampath1504 Sep 10 '17 at 21:36