The Observable.subscribe method does not get triggered upon calling the BehaviorSubject.next

In my Navbar component, I am attempting to determine whether the user is logged in or not so that I can enable/disable certain Navbar items. I have implemented a BehaviorSubject to multicast the data. The AuthenticationService class contains the BehaviorSubject object, as shown in the code snippet below:

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);
    }

    getOptions(){
        var jsonHeader = new Headers({
            'Content-Type':'application/json'
        });
        var options = new RequestOptions({
            headers: jsonHeader
        });
        return options;
    }
}

The AuthenticationComponent triggers the authentication process, and its code looks like this:

    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']);
                    }
                }); 
    }
}

Lastly, the NavbarComponent code is 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 referred to an example on Stack Overflow to write this code (source). Please let me know if you see any issues with it.

Answer №1

Issue arises from how you're declaring the provider in both components:

providers:[AuthenticationService]

Whenever a service is provided in a component, a new instance is created each time. Consider providing AuthenticationService at a higher parent component level and then injecting it into child components or during bootstrapping.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a custom data type for the Tanstack table filtering function

I developed a unique filter function specifically for enhancing the functionality of Tanstack Table by utilizing fuse.js. Despite my efforts, TypeScript consistently raises concerns when I try to define the type for my custom function. My goal is to alig ...

Looking to retrieve the request body in a route handler in Next.js version 13.2?

I encountered an issue while attempting to send a post request to my API. The problem arises when I try to access the request body within the route handler, resulting in the following error: Code: export async function POST(request: Request) { const ...

What is the best way to add all IDs to an array, except for the very first one

Is there a way to push all response IDs into the idList array, excluding the first ID? Currently, the code below pushes all IDs to the list. How can it be modified to exclude the first ID? const getAllId = async () => { let res = await axios({ m ...

Perform a function on Angular 5

In my database, there is a table named settings. I have 2 backend endpoints: one for getting settings and another for updating settings. Now I am working on creating an Angular window to edit this table. I've set up an Angular Service to retrieve va ...

Changes made to an array in a called method using TypeScript do not appear in the calling function

The angular 6 calling-component-code I'm working with is as follows: this.appDowntimeService.getAllApplications(this.message, this.appDetails); Here's the service method being called: async getAllApplications(message: any[], appDetails: any[ ...

Angular unable to register service worker

Looking to implement push notifications in my Angular app using vanilla JavaScript instead of the Angular service worker or @angular/pwa. In angular.json, I've specified the path to the js file under the script option. However, when the service worke ...

Exploring the versatility of Highcharts with callback functions and comprehensive

Currently, I am utilizing Highcharts with angular 9. Here is the link to the code : https://stackblitz.com/edit/angular-ivy-wdejxk For running on the application side or test side, follow these instructions: Test Side: In the angular.json file at line ...

Adding Text Above a Material Icon in Angular: A Guide

Here is some sample HTML code to consider: <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/> <mat-icon class="fa fa-folder" style="font-size:48px;"><span style="color: re ...

Do [(ngModel)] bindings strictly adhere to being strings?

Imagine a scenario where you have a radiobutton HTML element within an angular application, <div class="radio"> <label> <input type="radio" name="approvedeny" value="true" [(ngModel)]=_approvedOrDenied> Approve < ...

Typescript - Keeping a log of object keys along with their corresponding key type values

Imagine having the following scenario where you need to create an object with keys that are transformed versions of the original type's values: export type CCDTypes = { AuthorisationCaseEvent: AuthorisationCaseEvent, AuthorisationCaseField: Author ...

What causes an array of type `never[] & number[]` to be generated when using `Object.assign`?

Take a look at this code snippet: const arr = [1,2,3] const res1 = arr.slice() const res2 = Object.assign([],arr) When using arr.slice() to create a shallow clone, the resulting array res1 will have a type of number[], just like the original arr. However, ...

I am unable to locate the appropriate TypeScript type for the `displayName` attribute when it is used as a prop for the `type` component

Having trouble finding the correct type as mentioned in the title. After inspecting with DevTools, I have confirmed that every component I am programmatically looking at has Component.type.displayName. For anything that is not an ElementType, the type is a ...

Converting an array of arguments into tuples within the range of <T extends Tuple> is denoted by [T, (...args: NonNullArray<T>) => any], where each tuple represents the argument of a

Let's start with a simple function that takes a tuple as its first argument and a function whose arguments are elements of the tuple that are not null as its second argument: let first: number | null | undefined; let last: number | null | undefined; l ...

When the session times out in Angular 5, the previous user's credentials remain on the page instead of being replaced with the current user's information

When switching from one user to another in Angular 5, I am facing an issue where the previous user's credentials are displayed instead of the current user's until I refresh the page. I have tried using the localstorage.clear() method but it doesn ...

Angular 2's SVG creations do not resize properly

It is a common knowledge that an svg element with the attribute viewbox should automatically scale to fit the sizes specified in the styles. For instance, let's consider a 200*200 circle placed inside a 100*100 div. Prior to that, we need to ensure t ...

The 'string[]' type cannot be assigned to the 'string | ParsedUrlQueryInput | null | undefined' type in Next.js and Typescript

I'm facing an issue while attempting to transfer an array of strings from one page to another in Next.js using <Link href={{ pathname: "/model", query: data }}>. The problem arises when the query parameter is red underlined: Type &apos ...

Generating React Components Dynamically using TypeScript

Attempting to generate an element in React using Typescript based on the given tagName passed as props, along with additional relative element properties depending on that particular tagName. Take a look at the code snippet below: type ElementProps<Tag ...

Showing an error message upon submission in Angular 4 according to the server's response

Struggling for hours to display an error message when a form submits and returns an error status code. The solution seems elusive... In the login form component below, I've indicated where I would like to indicate whether the form is valid or invalid ...

What could be causing my vis.js network's node hover popups to not function properly?

I've encountered an issue where, despite adding the 'title' property to my node objects, the pop up window with the title content doesn't appear when I hover over a node. Here are the options I've chosen and how I've set up m ...

Is there a way to imitate the typeof operation on an object in TypeScript?

Today's challenge is a strange one - I've encountered a bug where the code behaves differently if typeof(transaction) returns object instead of the object name. To work around this issue, I introduced a new parameter called transactionType to my ...