Reputation: 13
I am new to angular and I am trying to pass data from one component(HomeComponent) to another component(ProfileComponent) after navigation.
I created a shared service(DataService). I injected the service in both the HomeComponent and ProfileComponent but when I set the value of the message property in HomeComponent and try to retrieve it in the ProfileComponent the value is undefined because the DataService is not the same instance.
The DataService was registered in the AppModule in the providers array so it should be a shared service and always the same instance right?
Thanks in advance
DataService.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DataService {
message:string;
constructor() { }
}
HomeComponent.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from '../services/data/data.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private data:DataService) { }
ngOnInit() {
this.data.message = "hello world";
}
}
ProfileComponent.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from '../services/data/data.service';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
private message : string;//undefined
constructor(private data:DataService) { }
ngOnInit() {
this.message = this.data.message;
}
}
AppModule.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { DataService } from './services/data/data.service';
import { HomeComponent } from './home/home.component';
import { ProfileComponent } from './profile/profile.component';
@NgModule({
declarations: [
AppComponent,
HomeComponent,
ProfileComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [DataService],
bootstrap: [AppComponent]
})
export class AppModule { }
Upvotes: 1
Views: 9573
Reputation: 83
I know it's a 2 year question, but Google puts it at the top of search results
Now, Angular docs are clearer about this (or just we can find out easier), it's called "Singleton Services" The section that explains this "bug" is The ForRoot Pattern and it says:
"If a module defines both providers and declarations (components, directives, pipes), then loading the module in multiple feature modules would duplicate the registration of the service. This could result in multiple service instances and the service would no longer behave as a singleton."
To sum up, if you define this in your services (DataService.ts) the providedIn: root
as follows
@Injectable({ providedIn: 'root' })
you need to avoid define the service as a provider on your components or modules.
AppModule.ts
...
imports: [
BrowserModule,
AppRoutingModule
],
providers: [DataService], // This line is the problem
bootstrap: [AppComponent]
....
Hope that helps to somebody and if need more documentation refer to Singleton Services' link
Upvotes: 6
Reputation: 222582
Each time you inject the service to your component, new instance is generated. However in this case i would recommend you to use BehaviorSubject as follows,
@Injectable()
export class SharedService {
private messageSource = new BehaviorSubject<string>("default message");
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
this.messageSource.next(message)
}
Upvotes: 4