Reputation: 1833
I have a header component that is using a "user-service" class to call an HTTP GET function to retrieve JSON data from a REST end point. The service works just fine and I can get the data, but I want this data to determine what controls appear on the page based on the current user's role. I need to pass the user data from the header component to all other components where I'm changing layout or privileges based on role, so I'm not calling the service GET function each time.
I have written a similar question and got a good start, but how do I specifically pass a "user" object from one component to another? If I can access the reference or just get the data from the current user from the header component in any other component I need it, that will be exactly what I'm looking for.
Thanks!
Upvotes: 2
Views: 1158
Reputation: 3605
There is another solution as well. Instead of using Ngrx store, you can use Angular Router.
Basically, it acts like a session and you can pass in any type of object you want, and direct it to any component you want.
Here is a great tutorial I found and I found it useful. I used this solution for my app and it works like a charm.
The link to the tutorial: https://www.thepolyglotdeveloper.com/2016/10/passing-complex-data-angular-2-router-nativescript/
Upvotes: 0
Reputation: 3605
I would use Ngrx store for this as it is the official way of getting data between components. Ngrx store is like a session that you can access across various components and that is its purpose.
Here is a great tutorial by Gary Simon on YouTube: https://youtu.be/9P5DTlg9oLc
Here is the written version of the video: https://coursetro.com/posts/code/151/Angular-Ngrx-Store-Tutorial---Learn-Angular-State-Management
Upvotes: 0
Reputation: 40896
Just store the user object in your user-service
, inject the service into components that need to see the user object, and implement a UserService.getUser
method that will return said objects to the components.
Ok after reading your OP and your comments below, I have a better understanding. You already know how to get the user into your component:
this.userService.getUser().subscribe(res => this.user=res);
Problem is that getUser()
is triggering an HTTP request each time and you want to avoid it right? Simplest thing would be to store the user object in the service the first time you retrieve it, and serve that instead the next time you're asked for it. Change your original method from:
getUser(): Observable<User> {
return this.http.get(this.url)
.map(res => res.json())
.catch(this.handleError);
}
To something like:
//null until the first http request
currentUser:User = null;
//will serve user from local copy if available. If not, will fetch from
//server, then save a local copy
getUser(): Observable<User> {
return !!this.currentUser? Observable.of(this.currentUser):
this.http.get(this.url)
.map(res => res.json())
//cache the result
.do((res:User)=>this.currentUser=res)
.catch(this.handleError);
}
If you create multiple instances of the service, you will still be making multiple http requests because each instance will hold its own cached currentUser
. You should instead have a singleton: a unique global instance.
To do this, add the service to the providers array of your root module.
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
providers: [ UserService ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Finally be sure to not include the service in any other module's or component's providers
array. Now you can inject the same instance of the service in any component that needs it
constructor(private userSvc:UserService){}
Upvotes: 3