I have a root module called "AppModule". "AppModule" lazy loads several other modules one of which is called "BooksAndRunModule". I have two components that belong to "BooksAndRunModule" that need to share the same instance of a service which I have named "BooksAndRunService". The first and only place I declare "BooksAndRunService" as a provider is in the "BooksAndRunModule". I thought by doing this my two components would have access to the same service instance but they do not. Obviously my understanding of dependency injection falls short. I don't want this service to be available app wide which is why I only declare it as a provider in the "BooksAndRunModule". What don't I understand and how can I make this work? Let me know if you would like to see any other file in my project.
AppModule:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppRoutingModule } from './app-routing.module';
import { AuthenticationModule } from './authentication/authentication.module';
import { SharedModule } from './shared/shared.module';
import { AppComponent } from './app.component';
import { FriendService } from './friend.service';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule,
AuthenticationModule,
SharedModule,
],
providers: [ FriendService ],
bootstrap: [AppComponent]
})
export class AppModule { }
BooksAndRunModule:
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { FriendService } from '../friend.service';
import { BooksAndRunCreateComponent } from './books_and_run_create.component';
import { BooksAndRunPlayComponent } from './books_and_run_play.component';
import { BooksAndRunService } from './books_and_run.service';
import { BooksAndRunRouter } from './books_and_run.router';
@NgModule({
declarations: [
BooksAndRunCreateComponent,
BooksAndRunPlayComponent,
],
imports: [
CommonModule,
SharedModule,
BooksAndRunRouter,
],
providers: [ FriendService, BooksAndRunService ],
})
export class BooksAndRunModule { }
BooksAndRunCreateComponent:
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { FriendList } from '../friendlist';
import { FriendService } from '../friend.service';
import { BooksAndRunService } from './books_and_run.service';
@Component({
moduleId: module.id,
selector: 'books-and-run-create',
templateUrl: './books_and_run_create.component.html',
styleUrls: ['./books_and_run_create.component.css'],
})
export class BooksAndRunCreateComponent implements OnInit {
constructor(public friendService: FriendService, private booksAndRunService: BooksAndRunService, private router: Router) { }
isRequesting: boolean;
name: string = 'Aaron';
friendList: FriendList[] = [];
players: any[] = [];
private stopRefreshing() {
this.isRequesting = false;
}
ngOnInit(): void {
this.booksAndRunService.resetPlayers();
this.isRequesting = true;
this.friendService
.getFriendList()
.subscribe(
data => this.friendList = data,
() => this.stopRefreshing(),
() => this.stopRefreshing(),
)
}
addPlayer(player): void {
this.booksAndRunService.addPlayer(player);
for(var i=0; i<this.friendList.length; i++) {
if(this.friendList[i].pk === player.pk) {
this.friendList.splice(i, 1);
}
}
this.players = this.booksAndRunService.getPlayers();
console.log("Current players are: " + this.players);
}
removePlayer(player): void {
this.booksAndRunService.removePlayer(player);
this.friendList.push(player);
this.players = this.booksAndRunService.getPlayers();
console.log("Current players are: " + this.players)
}
goToGame(): void {
console.log('Going to game with players: ' + this.booksAndRunService.getPlayers());
this.router.navigate(['/books_and_run/play'])
}
}
BooksAndRunPlayComponent:
import { Component, OnInit, AfterViewChecked } from '@angular/core';
import { BooksAndRunService } from './books_and_run.service';
import { Score } from './books_and_run.classes';
@Component({
moduleId: module.id,
selector: 'books-and-run-play',
templateUrl: './books_and_run_play.component.html',
styleUrls: ['./books_and_run_play.component.css'],
})
export class BooksAndRunPlayComponent implements OnInit, AfterViewChecked {
constructor(public booksAndRunService: BooksAndRunService) { }
game = { players: []};
ngOnInit(): void {
console.log("Initalizing BooksAndRunPlayComponent...")
console.log("Here are the players: " + this.booksAndRunService.getPlayers())
var game: any;
if(localStorage.getItem('game') === null) {
console.log("Creating a new game...");
this.game = this.booksAndRunService.prepareGame();
this.booksAndRunService.saveGame(this.game);
} else {
console.log("Restoring game from localStorage...");
this.game = this.booksAndRunService.restoreGame();
};
}
ngAfterViewChecked() {
this.booksAndRunService.saveGame(this.game);
}
}
BooksAndRunService:
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import { Game, Player, Score, Round } from './books_and_run.classes'
@Injectable()
export class BooksAndRunService {
players: Player[];
getPlayers() {
return this.players;
}
addPlayer(player) {
this.players.push(player);
}
removePlayer(player) {
for(var i=0; i<this.players.length; i++) {
if(this.players[i].pk === player.pk) {
this.players.splice(i, 1);
}
}
}
resetPlayers() {
this.players = [];
}
}
The simplest answer is to just provide this service in the providers array in the app module.
@NgModule({
providers: [ BooksAndRunService ]
})
class AppModule {}
The reason for this is nicely covered here in a compilation of official explanations of the subject. In short, lazy loaded modules have their own root scope. You can use forRoot() instead, but this essentially accomplishes the same thing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With