I am trying to get whether user is loggedIn or not in my Navbar component so I can unable/disable Navbar items. I am using BehaviorSubject to multicast the data. My AuthenticationService holds the BehaviorSubject object as you can see in the following code:
import {Injectable} from '@angular/core';
import {Http, RequestOptions, Headers} from '@angular/http';
import {LocalStorage, SessionStorage} from "angular2-localstorage/WebStorage";
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Credentials} from './credentials';
@Injectable()
export class AuthenticationService {
private _baseUrl="http://localhost:8080/webapi/authenticate/";
private loggedIn: boolean;
// Observable UserLoggedIn source
private _userLoggedInBehavior = new BehaviorSubject<boolean>(false);
// Observable UserLoggedIn stream
userLoggedInBehaviorStream = this._userLoggedInBehavior.asObservable();
constructor(private _http: Http){
this.loggedIn = localStorage.getItem("authToken");
}
authenticate(credentials: Credentials){
return this._http.post(
this._baseUrl
, JSON.stringify(credentials)
, this.getOptions()
)
.map(res => res.json())
.map((res) => {
if (res.success) {
sessionStorage.setItem("authToken", res.data.token);
this.loggedIn = true;
}
return res.success;
});
}
logout() {
sessionStorage.removeItem("authToken");
this.loggedIn = false;
}
isLoggedIn() {
return this.loggedIn;
}
changeUserLoggedInBehavior(loggedIn) {
this._userLoggedInBehavior.next(loggedIn);
}
// This was necessary because api accepts only JSON
// and if we do not put this header in requests API
// responds with 415 wrong media object.
getOptions(){
var jsonHeader = new Headers({
'Content-Type':'application/json'
});
var options = new RequestOptions({
headers: jsonHeader
});
return options;
}
}
My AuthenticationComponent code which triggers the code looks as follows:
import {Component, OnInit, EventEmitter} from '@angular/core';
import {CanDeactivate, Router} from '@angular/router-deprecated';
import {ControlGroup, Control, Validators, FormBuilder} from '@angular/common';
import {AuthenticationService} from './authentication.service';
import {Credentials} from './credentials';
import {EmailValidator} from '../../validators/email-validator';
@Component({
selector:'auth'
, templateUrl:'app/components/authentication/authentication.component.html'
, providers:[AuthenticationService]
})
export class AuthenticationComponent{
form: ControlGroup;
title: string = "LogIn";
credentials: Credentials = new Credentials();
constructor(
fb: FormBuilder
, private _authService: AuthenticationService
, private _router: Router){
this.form = fb.group({
emailId:[
''
, Validators.compose(
[
Validators.required
, EmailValidator.mustBeValidEmail
]
)
]
,password:[
''
, Validators.compose(
[
Validators.required
]
)
]
});
}
save(){
this._authService.authenticate (this.credentials)
.subscribe((result) => {
if (result) {
this._authService.changeUserLoggedInBehavior(true);
this._router.navigate(['Home']);
}
});
}
}
Last, My NavbarComponent as follows:
import {Component, OnInit, OnDestroy} from '@angular/core';
import {RouterLink} from '@angular/router-deprecated';
import {Subscription} from 'rxjs/Subscription';
import {AuthenticationService} from '../components/authentication/authentication.service';
@Component({
selector:'navbar'
, templateUrl: 'app/navbar/navbar.component.html'
, directives:[RouterLink]
, providers:[AuthenticationService]
})
export class NavbarComponent implements OnInit, OnDestroy{
private _isUserLoggedIn: boolean=false;
subscription: Subscription;
constructor(
private _authService: AuthenticationService
){}
ngOnInit(){
this.subscription = this._authService.userLoggedInBehaviorStream
.subscribe(
loggedIn => this._isUserLoggedIn = loggedIn
);
}
ngOnDestroy(){
// prevent memory leak when component is destroyed
this.subscription.unsubscribe();
}
public setUserLoggedId (isLoggedIn: boolean){
this._isUserLoggedIn = isLoggedIn;
}
}
I have used this as an example to write the code. Please let me know where I am going wrong.
The problem is that in both of your components you are specifying provider:
providers:[AuthenticationService]
Every time in component you provide some service it will get new instance. Try to provide AuthenticationService in some parent component and just inject in child components or on boot level.