3

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.

Community
  • 1
  • 1
Darshan Puranik
  • 1,055
  • 3
  • 14
  • 36

1 Answers1

6

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.

Admir Sabanovic
  • 645
  • 1
  • 11
  • 18
  • Your suggestions worked. I added the AuthenticationService to boot level as I am gonna use it multiple times in my application. Can you point me to documentation which elaborates on your suggestions so I can educate myself. – Darshan Puranik Jun 16 '16 at 13:32
  • 1
    I think it is described in this part here: https://angular.io/docs/ts/latest/guide/dependency-injection.html – Admir Sabanovic Jun 16 '16 at 13:41