What is the best way to show specific links in the navigation bar only when the user is signed in using Angular?

I'm attempting to customize the navigation bar to display "Sign In" and "Sign Up" buttons only when the user is not signed in, and show the message and profile navigation items when the user is signed in.

Below is the provided code snippet:

Token Service

...
  SetToken(token) {
    this.cookieService.set('chat_token', token);
  }

  GetToken() {
    return this.cookieService.get('chat_token');
  }

  DeleteToken() {
    this.cookieService.delete('chat_token');
  }

  GetPayload() {
    const token = this.GetToken();
    let payload;
    if (token) {
      payload = token.split('.')[1];
      payload = JSON.parse(window.atob(payload));
    }

    return payload.data;
  }
}

Authguard Service

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {
    const token = this.tokenService.GetToken();
    if (token) {
      return true;
    } else {
      this.router.navigate(['/']);
      return false;
    }
  }
}

Header.ts

  constructor(public nav: HeaderService, private tokenService: TokenService,
    private router: Router,
    private usersService: UsersService,
    private msgService: MessageService
  ) {
    this.socket = io('http://localhost:3000');
  } 

  ngOnInit() {
    this.user = this.tokenService.GetPayload();
    ...  

HTML

<nav *ngIf="nav.visible" class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">
    <img src="../assets/images/close.png" class="img-fluid" style="width:50px; height:50px" alt="">
  </a>

  <button class="navbar-toggler" type="button"
  (click)="toggleNavbar()">
<span class="navbar-toggler-icon"></span>
</button>


<div class="collapse navbar-collapse"
[ngClass]="{ 'show': navbarOpen }">
<ul class="navbar-nav ml-auto">

      <li class="nav-item">
        <a class="nav-link" routerLink="/home" >Item 1</a>
      </li>

      <li class="nav-item signin">
        <a class="nav-link" routerLink="/sign-in" >Sign in</a>
      </li>

       <li class="nav-item signup">
        <a class="nav-link" routerLink="/sign-up" >Sign Up</a>
      </li>
      <li class="nav-item dropdown ml-auto" appdropdown #r="appdropdown">

          <a class="nav-link dropdown-toggle toolbar-image" href="" onclick="return false;" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              <i class="material-icons">forum</i>
            <span>2</span> 
          </a>
          <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdownMenuLink">
              <div class="sidebar-scroll" id="list-group">
            <a class="dropdown-item chat" href="#">

                        <img src="http://emilcarlsson.se/assets/donnapaulsen.png" class="rounded-circle">
                        <div class='message'>
                        <h3 class="d-xs-none username">Jessica</h3>
                        <p class="d-xs-none letter">StanIsLove aaaaaaaaaaaaaaaaa.</p>
                        </div>
                        <p>17m ago</p>
                      </a>
                </div>
            </div>

        </li>
        <li class="nav-item dropdown ml-auto" appdropdown #r="appdropdown">
            <a class="nav-link dropdown-toggle" href="" onclick="return false;" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <img src="http://emilcarlsson.se/assets/donnapaulsen.png" class="rounded-circle profile">
            </a>
            <div class="dropdown-menu dropdown-menu-right avatar" aria-labelledby="navbarDropdownMenuLink">
                <div class="sidebar-scroll" id="list-group">
              <a class="dropdown-item chat" href="#">
                  <span class="d-xs-none username">Profile</span>  
                        </a>
                        <a class="dropdown-item chat" href="#">
                            <span class="d-xs-none username">Settings</span>  
                                  </a>
                                  <a class="dropdown-item chat" href="#">
                                    <span class="d-xs-none username">Logout</span>  
                                          </a>

                  </div>
              </div>


          </li>

    </ul>
  </div>
</nav>

I believe integrating this.tokenService.GetPayload() into the HTML and utilizing "ngIf" should work. However, I am uncertain. How can I address this issue to only display "Sign In" and "Sign Up" links for non-signed-in users, and show the last two drop-downs exclusively for signed-in individuals?

Answer №1

1.) It is important to refrain from invoking component's methods within your html template. More details on this topic can be found here

2.) In the file header-component.ts, make sure to include your service in the constructor, create a class property, fetch the token using your service, and assign it to your class property.

export clas HeaderComponent implements OnInit:

  private isLogged: boolean;

constructor(private tokenService: TokenService){

  public ngOnInit() { 
    this.isLogged = this.tokenService.GetPayload() !== null; // Assuming that user is logged if there is a payload present, you may need to adjust the condition
  }
}

3.) Within your header.component.html, verify whether the user is logged in order to display specific elements.

<div *ngIf="isLogged">...</div>

4.) It is imperative to update your GetPayload() method. If there is no token available, your code will throw an error stating

TypeError: Cannot read property data of undefined

GetPayload() {
    const token = this.GetToken();
    if (!token) {
      return null;
    }
    const payload = Json.parse(window.atob(token.split('.')[1]);
    return payload.data;
  }

Now that the GetPayload method can potentially return null, exercise caution when calling it and ensure that the result is not null before utilization.

Answer №2

To determine if a user is logged in and disable/hide links, the server should send a check to the client using a service that maintains login status for any component to query. In your specific situation, you can implement a structural directive *ngIf="user" within your tags to verify if the user is set before displaying the links.

<li *ngIf="user" class="nav-item">
  <a class="nav-link" routerLink="/home" >Item 1</a>
</li>

If your goal is just securing routing, consider using the AuthGuard. https://angular.io/guide/router#canactivate-requiring-authentication.

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

The lack of space within the <mat-select> component is causing some issues. Is there a way to incorporate multiple lines within the <

Is there a way to display multiple lines of text for each option in mat-select, instead of limiting the characters and adding "..." at the end? I need the options to have additional description lines. Here is a StackBlitz demo showcasing my issue: https:// ...

Transforming strings of HTML into objects in the DocX format

After developing a TypeScript script that transforms a JSON string into a Word Doc poster using Docx, I encountered a hurdle. Certain sections of the JSON may contain HTML tags, such as <br/>, <i>, <p>, and I need a way to pass the stri ...

Encountering an error message that states "Unable to read property 'next' of undefined" while utilizing the async

Operating a service similar to this involves simulating an API call. import { Injectable } from '@angular/core'; import { Observable, Subscriber} from 'rxjs'; import { DeviceStatus } from '../models/device-status-model'; @I ...

A step-by-step guide on leveraging swagger-autogen in TypeScript applications

Is it possible to integrate the swagger-autogen module into a Typescript project? I have attempted multiple methods, but have been unsuccessful. The error message "Failed" keeps appearing when using a swagger.js file: const swaggerAutogen = require("swagge ...

The enum cannot be assigned a type of 'string | null'

Within my ProductGender enum, I have: enum ProductGender { Men, Women, } In my getProducts service: public getProducts( gender: ProductGender, category: ProductCategory ): Observable<IProductInterface[]> { return this.httpPro ...

Encountering a syntax error when attempting to utilize the colon symbol for specifying data types

Currently, I am a novice who is delving into the world of TypeScript. Here is a snippet of code that I have written: let num: number = 123; console.log(123); However, when attempting to run this file using Node.js and saving it as test.ts, I encounter the ...

React with Typescript: Potential occurrence of an undefined object

While working with React and TypeScript, I encountered the error Object is possibly 'undefined' when using language.toLowerCase().includes(selectedCategory). To address this issue, I implemented a check as shown below. Although this resolved th ...

Issues have arisen with compiling TypeScript due to the absence of the 'tsc command not found' error

Attempting to set up TypeScript, I ran the command: npm install -g typescript After running tsc --version, it returned 'tsc command not found'. Despite trying various solutions from Stack Overflow, GitHub, and other sources, I am unable to reso ...

What is the correct approach for detecting object collisions in Phaser 3?

Hey everyone, I'm facing a problem and could use some assistance. Currently, I am trying to detect when two containers collide in my project. However, the issue is that the collision is being detected before the objects even start moving on screen. It ...

Unusual behavior observed in Angular 2 when handling button click events

In my .ts file, there are two straightforward methods: editLocation(index) {} deleteLocation(index) { this.locations.splice(index, 1); } The corresponding HTML triggers these methods when buttons are clicked: <button (click)="editLocation(i)" ...

Utilizing activatedRoute in Angular to retrieve encoded query parameters

I am facing an issue with my Angular application, where it is loaded after being redirected from another application. I need to access query parameters when the authentication website returns to my Angular application. The URL appears as: http://localhost ...

Typescript compiles only the files that are currently open in Visual Studio

In my Visual Studio Typescript project, I am in the process of transforming a large library of legacy JavaScript files by renaming them to *.ts and adding type information to enhance application safety. With over 200 files to modify, it's quite a task ...

When using TypeScript, it is important to ensure that the type of the Get and Set accessors for properties returning a

Why is it necessary for TypeScript to require Get/Set accessors to have the same type? For example, if we want a property that returns a promise. module App { export interface MyInterface { foo: ng.IPromise<IStuff>; } export int ...

Tips for integrating external libraries (npm packages) in Ionic 4 applications

With the changes in Ionic 4, I am seeking a definitive guide on implementing third party libraries, such as "rss-parser". I have reviewed this article which seems to be the latest resource on the topic: https://ionicframework.com/docs/v3/developer-resour ...

Building a Next.js application that supports both Javascript and Typescript

I currently have a Next.js app that is written in Javascript, but I am looking to transition to writing new code in Typescript. To add Typescript to my project, I tried creating a tsconfig.json file at the project root and then ran npm install --save-dev ...

Utilizing ngClassEven and ngClassOdd in Angular 2 for Improved Styling

I attempted to replicate the behavior of ng-class-even and ng-class-odd (originally from Angular 1) in my Angular 2 application. Below is the code I wrote and it's functioning correctly, but I'm curious if there are alternative methods to achiev ...

Angular 4: Conditional CSS classes causing issues with transitions

After scouring through stackoverflow, I have yet to find a solution to my current issue. I am utilizing a conditional class on a div that is applied when a boolean variable becomes true. Below is the code snippet in question: <div [class.modalwindow-sh ...

What is the best way to combine index signatures with established properties?

Imagine a scenario where an interface has certain defined properties with specific types, but can also include additional properties with unknown keys and various other types. Here is an example: interface Bar { size: number; [key: string]: boolean | s ...

Error in Angular TypeScript occurs when attempting to read properties of an undefined value

Here is the interface that I am working with: export interface IQuest { Id: number, lat: number, lon: number, Question:string, Answer:boolean, IsDone:boolean, Correct:boolean, Range:number} Along with the following component: export class AppComponent imp ...

Ensure that the tooltip remains visible within the confines of the page

In my Angular application, I have successfully implemented a versatile tooltip feature that goes beyond just displaying text. The tooltip is a div element that has the ability to contain various contents: .tooltip-master { position: relative; .tooltip ...