I am attempting to share a string between two sibling components within Angular, but it does not appear to be working for me.
I have two components, auth.component.ts
and update.component.ts
. I then have a service called shared.service.ts
.
EDIT 2: I am including the entire shared.services.ts file as per the recommendation in the comments.
shared.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SharedService {
private useridSource = new BehaviorSubject('empty');
useridMessage$ = this.useridSource.asObservable();
constructor() { }
sendUserId(userId:string) {
this.useridSource.next(userId);
}
}
The purpose of the auth
component is to allow a user to login/sign up via firebase's authentication methods. I then retrieve the User's Unique ID and want to pass that string on to the update.ts
component so that it can create a node under that name in the Firebase Real Time Database. Please note that I am also using the Angular Fire Library when working with firebase.
Here are the snippets of code from auth.component.ts
//I store the unique ID created by firebase in this string
userId?:string;
//I inject the AngularFireAuth from the Angular Fire library as well as my Shared Service
constructor(public auth: AngularFireAuth, private sharedService: SharedService ) { }
//the user logs in or signs up using google
login() {
this.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
}
//this function sets the userId string - if I console.log() this string, it prints out correctly
printUserId() {
this.auth.authState.subscribe( authState => {
this.currentAuth = authState;
this.userId = this.currentAuth.uid;
})
}
//I use this function to send the data via the shared service when a button is pressed in the HTML file.
sendUserData(){
if(this.userId) {
console.log(this.userId);
this.sharedService.sendUserId(this.userId);
} else {
console.log("User Id has not been set");
}
}
In the auth.component.html file, I send the data to the service by:
<button (click)="sendUserData()"> Send Current User </button>
In update.component.ts, I received the data and want to print it out.
//string to receive the data in
userId?:string;
//inject the shared service. The CrowboxdbService is another service I use to interact with firebase
constructor(private cbservice: CrowboxdbService, private sharesService: SharedService) {
}
//this function is invoked when a button is pressed in the view (HTML file)
getUserId(){
this.sharesService.useridMessage$.subscribe(x => {
this.userId = x;
console.log(this.userId);
}
);
}
In the update.component.html
<button (click)="getUserId()">Get User ID </button>
<h1>User Id is: {{userId}}</h1>
So when I attempt to send the data through sendUserData()
in the auth.component.ts file, it works. I am able to print the User Id in the console window as well. In update.component.ts, however, when I subscribe to the observable, I still receive "empty". Does this mean that it is not changing the value?
I have tried subscribing to the observable in ngOnInit()
in both the ts
files but that still does not return the proper value. Am I missing something? I have been following this tutorial.
EDIT 1: Important note (I think?), the two components also serve as two different routes. Here are the routes set up in app-routing.module.ts
const routes: Routes = [
{ path:'', component:TestUpdateComponent },
{ path:'auth', component:AuthComponentComponent }
];
CodePudding user response:
Well, I checked your code and the problem may caused by lots of reasons but I think the problem is that you provided this service in multiple modules.
Make sure that you only provide this service in one module that declared both components or in the app.module.ts
My suggestion is to create a components.module.ts
and declare all your components there so you can import it where ever you want.
I also recommend you to declare a public variable in the service instead of this confusing setters and getters so you can update it every where and it will update in other places.
CodePudding user response:
The issue was actually to do with the fact that I was attempting to share data between components that are in different routes. As a result, these are unrelated components and I could not use the standard methods of sharing data (e.g. from parent to child or between sibling components).
I followed the third example from this website. I created a simple service through ng g s shared
command. I imported this service into my app.module.ts file and included it as one of the providers
.
The shared.service.ts file is very simple, as I only want to pass one string:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class SharedService {
public userId:any;
constructor() { }
}
Then, in auth.component.ts, the file which needed to send the data, I had a function that was executed upon the click of a button. This function checked if the string in question had been set previously (by the user logging in in this case). If he string was set, it then set the string in the provider file and navigated to the receiver component page.
//function is invoked by a button in the view page
sendUserData(){
if (this.userId) {
this.sharedService.userId = this.userId;
this.router.navigate(['data']);
} else {
console.log("User Id has not been set");
}
}
To receive the data in update.component.ts, I had a simple function that was also executed upon the click of a button:
getUserId(){
this.userId = this.sharesService.userId;
console.log(this.userId);
}
And this prints out the value. If I am not mistaken, this method also makes the variable globally available to all components that have access to this specific provider.