Updating the sidebar component in Angular 11 post successful login

Recently, I delved into the world of Angular with a goal to learn more about its functionality. I encountered an issue with my sidebar component that remains static even after logging in:

Click here to view my sidebar text

Upon successful login, the register and login texts should disappear and be replaced with the following:

Check out the updated sidebar post-login & refresh

The changes are only reflected when I manually refresh the page (using F5).

Interestingly, upon using the logout function, the sidebar updates correctly without requiring a manual refresh.

I am sharing some code snippets below that might shed light on the scenario:

side-bar.component.html

<p *ngIf="authService.isAuthenticated">{{message}}</p> 
<li *ngIf="!authService.isAuthenticated"><a routerLink="/register">Register</a></li>
<li *ngIf="!authService.isAuthenticated"><a routerLink="/login">Login</a></li>
<li *ngIf="authService.isAuthenticated"><a routerLink="/home" (click)="logout()">Logout</a></li>

side-bar.component.ts

message = ''
ngOnInit() {
    if(this.authService.isAuthenticated)
    {
        this.authService.getUser()
        console.log("user is logged in")
        this.message = `Welcome`
    }
    else
    {
        console.log("user is not logged in")
    }
    
}



logout(): void {
    this.authService.logout()
}

auth-service.service.ts

get isAuthenticated() {
    return !!localStorage.getItem(this.TOKEN_KEY)
}

logout() {
    localStorage.removeItem(this.TOKEN_KEY)
    this.http.post(this.API_URL + '/logout', {})
    this.router.navigateByUrl('/home')
}

login(user: string, pass: string) {    
    const data = {
        username: user,
        password: pass
    }

    this.http.post(this.API_URL + '/login', data, { withCredentials: true }).subscribe(
        (res: any) => {
            console.log(res)
            localStorage.setItem(this.TOKEN_KEY, res.token.value)
            this.router.navigateByUrl('/home')
        }
    )
}

getUser() {
    this.http.get(this.API_URL + '/user', {withCredentials: true}).subscribe(
        (res) => {
            console.log(res)
        }
    )
}

If you have any suggestions, please do share them. Your input is highly appreciated.

Answer №1

When working with the API call, it's important to note that the asynchronous nature of the process means that the hook ngOnInit will only be triggered once during component initialization. To ensure a smooth operation, consider making the authentication check asynchronous as well. It may also be beneficial to move subscriptions from the service to the components themselves.

Give this a try:

Service

isAuthenticatedSrc: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

get isAuthenticated(): Observable<boolean> {
  return this.isAuthenticatedSrc.asObservable();
}

login(user: string, pass: string): Observable<any> {
  const data = {
    username: user,
    password: pass
  }

  this.http.post(this.API_URL + '/login', data, { withCredentials: true }).pipe(
    tap((res: any) => {
      this.isAuthenticatedSrc.next(true);
      localStorage.setItem(this.TOKEN_KEY, res.token.value);
    }),
    catchError((error: any) => {
      this.isAuthenticatedSrc.next(false);
      // handle error
      return throwError(error);
    })
  );
}

logout(): Observable<any> {
  return this.http.post(this.API_URL + '/logout', {}).pipe(
    tap(() => localStorage.removeItem(this.TOKEN_KEY))
  );
}

getUser(): Observable<any> {
  return this.http.get(this.API_URL + '/user', { withCredentials: true });
}

login.component.ts

ngOnInit() {
  this.authService.login(user, pass).subscribe({
    next: (res: any) => this.router.navigateByUrl('/home'),
    error: (error: any) => console.log(error)
  });
}

side-bar.component.ts

logout() {
  this.authService.logout().subscribe({
    next: () => this.router.navigateByUrl('/home'),
    error: (error: any) => console.log(error)
  });
}

side-bar.component.html

<ng-container *ngIf="(authService.isAuthenticated | async) as authenticated; else unauthenticated">
  <p>Welcome</p>
  <li><a routerLink="/home" (click)="logout()">Logout</a></li>
</ng-container>

<ng-template #unauthenticated>
  <li><a routerLink="/register">Register</a></li>
  <li><a routerLink="/login">Login</a></li>
<ng-template>

Answer №2

The most efficient approach is to implement a getter method for the message within your component, rather than setting it in the ngOnInit function.

Here's an example:

get message() {
    return this.authService.isAuthenticated ? 'Welcome' : '';
}

Alternatively, a more advanced and preferable method involves utilizing observables to dynamically change the value of the message.

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

Is it possible to utilize a partial entity for saving with TypeORM?

My current table structure looks like this: --changeset 0004-order:ccushing create table if not exists "order"."order" ( id uuid primary key not null default uuid_generate_v4(), state uuid re ...

Nuxt3 - TS2339: The 'replaceAll' property is not found on the 'string | string[]' type in Nuxt3

Hey there! I've been experimenting with the replaceAll() method within my Nuxt3 project and encountered a strange error. Folder Structure ───pages │ └───Work │ │ index.vue │ │ [Work].vue Template <templat ...

Directive for Angular 4 Confirmation Popups

I am currently working on creating a directive for implementing jQuery Confirm within an Angular 4 project. I am facing difficulties in preventing bound events from triggering. Below is the structure I have set up: menus.component.html: <a (click)="de ...

Ways to statically type a function that produces an array from 1 to n

I am working on creating a function that can generate an array of numbers ranging from 0 to n, while ensuring that the returned type matches a known array structure at compile time. const makeFoo = (n: number) => [...Array(n).keys()]; const foo1 = [0, 1 ...

Transitioned to Angular 16: Issues with Compiling Due to Google Places Autocomplete Plugin (ngx-google-places-autocomplete)

I am currently seeking support for implementing Google Places Autocomplete on mobile devices in portrait mode for iOS version 16.x (as well as Android). After upgrading our Angular web application from version 14 to 15 and then to 16, we encountered an iss ...

When Electron combines with Angular 4, the expected two-way data binding functionality fails to work

Each time the UI needs updating, developers are required to use the zone.run() method, which is not ideal as it adds repetitive code and lacks intuitiveness. Our main dependencies include: "dependencies": { "@angular/animations": "4.0.0", "@angular/com ...

What is the process for listening to custom events in Angular 4 components that have been loaded using routing?

In the app.component.html file <li routerLinkActive="active current"> <a [routerLink]="['/stats']"> Cluster stats </a> </li> When we route to the DisplayAllStatsComponent, how can we ...

Interacting Components in Angular 2/5

I am facing an issue with my guard-service where I need to change the member of my app.component. To achieve this, I have created a setter in app.component and it should be executed by the guard-service using Input and Output. import {AppComponent} from & ...

Encountering a problem while compiling the Next.js app

Whenever I execute the command npm run build for a Next.js project (built with React and TypeScript), I encounter the following error: Error: Missing "key" prop for element in array react/jsx-key This issue is specifically related to the following piec ...

Error Message: ES5 mandates the use of 'new' with Constructor Map

Below is the code snippet: export class ExtendedMap<T, U> extends Map { constructor() { super(); } toggle(key: T, value: U) { if (this.has(key)) { super.delete(key); ...

Tips for composing content on a sanitized input?

In my small application, I have a feature where a question is displayed with certain words hidden and needs to be filled in by the user. The format of the question looks like this: The {0} {1} {2} his {3} off To achieve this functionality, I wrote the f ...

What is the method for opening the image gallery in a Progressive Web App (PWA)?

I am struggling to figure out how to access the image gallery from a Progressive Web App (PWA). The PWA allows me to take pictures and upload them on a desktop, but when it comes to a mobile device, I can only access the camera to take photos. I have tried ...

What makes it impossible to use var instead of let in ngFor?

My understanding is that in JavaScript, we typically use var and let for variable declarations. The main difference between the two is that var is scoped to the current function, while let is scoped to the current block. Therefore, theoretically I should b ...

Option in TypeScript to retain the '//' in the filename when removed

I'm currently attempting to implement the angular2 quick start example in my local environment. The only feasible way for me to serve the application is as a plugin within an existing application on my system. This particular application hosts a web ...

Utilizing Angular 2 for transforming JSON data into Angular classes

I have been working through the Angular2 getting started guide to kickstart my own application development. So far, I have managed to retrieve JSON objects from a local file and display them in angular2 templates. However, the challenge arises when the str ...

React / NextJS: Repeating Audiowave Component

I am currently developing a chat application in NextJS that includes text-to-speech functionality. To visualize the audio playback waveform, I have integrated a third-party library called wavesurfer.js Though the audio implementation is functioning proper ...

Experiment with Google Sign-In authentication in jest with Firebase

As I try to effectively mock firebase authentication with Google login, I am encountering some difficulties. Below is the code that I am currently working with: simple.tsx import React, { Component } from 'react'; import * as firebase from &apo ...

When sending an HTTP POST request to a Nodejs service with an uploaded file, the request fails after 8-15 seconds on Firefox and 25 seconds on Chrome

My web app is built on Angular 7. I am facing an issue while trying to send larger files to a Node.js service. Smaller files, around 3mb, are being sent successfully but when attempting to send bigger files like 20mb, the request gets cut off. In Chrome, I ...

Strategies for resolving linter problems involving mixins in vue-typescript

Scenario: I am currently working on a project where I am implementing mixins to engage with data from components and other methods. Despite the code functioning as expected, I am encountering errors in Vetur indicating that the method does not exist in ...

Can you explain the concept of TestBed in Jasmine?

Recently, I have started using Jasmine with Angular 2 and have encountered an issue while working with the TestBed object in my test cases. The error message reads as follows: Please call "TestBed.compileComponents" before your test. Can anyone advise on ...