Update a specific element within Angular framework

Just starting out with angular and facing a seemingly simple issue that I can't seem to solve despite trying various solutions found on SO. I have created a login component where upon submission, the user is redirected to their profile page. While I am able to successfully redirect the user, the navigation bar at the top does not auto-refresh as intended. My goal is to have the navigation bar show the "Logout" button instead of the "Login/Register" button once the user logs in. Here's how my code files are structured:

login-page.component.html

<form #loginForm="ngForm" (ngSubmit)="loginUser(loginForm)" id="loginForm" class="loginbackground">
<input ngModel #emailAddress="ngModel" type="text" autocomplete="off" placeholder="Email" id="emailAddress" name="emailAddress" />
<button type="submit" id="submit">LOGIN</button>

login-page.component.ts

@Output() refreshEvent = new EventEmitter<any>();
loginUser(event) {
// Validations. If successful, proceed

const formData = event.value;
this.auth.loginUser(formData);
  .subscribe(data => {
    localStorage.setItem('loggedUser', JSON.stringify(data.userdata));
    // Form submit action here
    if (data.userdata.resMsg === 'Login failed') {
      this.errorPopup = true;
      this.errorText = 'Email Address and Password do not match';
    } else {
      this.refreshEvent.emit();
      this.emailAvailable = true;
      this.showLogin = false;
      this.showRegister = false;
      this.router.navigateByUrl('/404', { skipLocationChange: true }).then(() =>
        this.router.navigate(['user-profile']));
    }
  });
});
}

Problem
The issue arises when the nav bar doesn't update automatically after login. Manually refreshing the page resolves the problem but that's not ideal. I need the nav bar to reflect changes upon user login without needing manual intervention.

What I've tried

  • I attempted to implement the solution suggested here, but it didn't work for me.
  • Despite using an event emitter as shown above, I couldn't get it to function properly.
  • I also experimented with reloading the entire page using ngOnInit() to refresh the navigation bar component, but it caused an infinite loop. This was obviously a workaround, but I explored it nonetheless.

Is there a more elegant and effective way to achieve the desired outcome?

Answer №1

This is the method I used to solve the problem:

navigation.component.html

...
<li *ngIf="!authenticationService.checkLoginStatus()">
  ...
</li>
<li *ngIf="authenticationService.checkLoginStatus()">
  ...
</li>
...

navigation.component.ts

export class NavigationComponent implements OnInit {

  constructor(public authenticationService: AuthenticationService) {
  }
  ...

authentication.service.ts

export class AuthenticationService {
  ...
  public checkLoginStatus() {
    return this.getUserId() !== null;
  }
  ...

In the 'checkLoginStatus' method, the 'this.getUserId()' function is used to retrieve the token from localStorage.

Answer №2

Dealing with user authentication in Angular requires utilizing common features of the framework to ensure smooth functionality. Here is a breakdown of the process and sample code snippets to guide you through:

Thought process:

Problem: Ensuring constant awareness of the user's login status.
Solution: Implementing a service to track the user's login state.

Problem: Dynamic navigation bar based on user authentication.
Solution: Utilizing the authentication service to conditionally display navigation items according to the user's login status.

Code level issues:
Identifying code hurdles that may impede further development dependent on authentication status.

I've outlined two steps for enhancing your code. The first step focuses on improving data flow and code quality, while the second step offers a more dynamic approach.


Step 1

Service
Establish a variable within the Authentication Service to monitor the user's login status:

private isUserLoggedIn: boolean = false;

Migrate all authentication logic into the Authentication Service. Assume control over the this.auth.loginUser(formData) function by calling it from the new service and integrating its content into the revised login function.
Convert the HTTP call for login from an observable to a promise using .toPromise(), given its single-response nature.

The revised login function interacting with the API should resemble this:

private apiLogin(formData): Promise<any> {
        // Place the authentication logic here (use the relevant code from this.auth.loginUser(formData))
        // Presume 'loginObservable' holds the response from 'this.auth.loginUser(formData)'
        return new Promise((resolve, reject) => {
            this.auth.loginUser(formData)
                .toPromise()
                .then(data => {                   
                    if (data.userdata.resMsg === 'Login failed') {
                        localStorage.removeItem('loggedUser');
                        this.isUserLoggedIn = false;
                        reject('Email Address and Password do not match');
                    } else {
                        localStorage.setItem('loggedUser', JSON.stringify(data.userdata));
                        this.isUserLoggedIn = true;
                        resolve();
                    }
                })
                .catch(error => {
                    this.isUserLoggedIn = false;
                    reject(error);
                });
        })
    }

Implement a check to verify user login through local storage for seamless login experience across sessions:

// Check user login status via local storage
    private isAlreadyLoggedIn(): boolean {
        return !!localStorage.getItem('loggedUser');
    }

Introduce a login function triggered upon click events, bridging the service-calling component:

public login(formData): Promise<any> {        
        if (this.isAlreadyLoggedIn) {
            return Promise.resolve();
        } else {
            return this.apiLogin(formData);
        }
}

Add a constructor to initialize user login status verification & expose a public method for external status tracking:

constructor() {
        this.isUserLoggedIn = this.isAlreadyLoggedIn()
}
public isLoggedIn(): boolean {
        return this.isUserLoggedIn;
}

Complete service integration as demonstrated above.

Login Component:
Tweak component behavior to redirect already logged-in users to profile pages. Ensure error handling for better user interaction.

@Component({
    selector: 'app-login'
})
export class LoginComponent implements OnInit {
    ...
}
... (Content too long, request timed out) ...

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

An empty constant object can trigger an endless cycle of re-rendering

Consider this simplified scenario: export function myCustomHook<TData = Record<string,string>> (data?: TData) { const [output, setOutput] = useState<number>(); const customFunction(data?: TData) { //In a real scenario : p ...

Using a personalized domain with a Cloud Function to send a POST request

While I may not be the most experienced with Node.js, I am quickly learning and have a good grasp of JavaScript. Currently, I'm working on a project where I am utilizing Cloud Functions to build an API. My goal is to use a custom domain to access this ...

Unable to access due to CORS policy restriction in Ionic 5 Angular platform

Encountering an error, seeking guidance on the issue. Configuration has been done in proxy.conf.json. Headers with base url have been set in user.service.ts. import { Injectable } from '@angular/core'; import { Http, Headers, RequestOptions } fr ...

Is there a way for me to remove an uploaded image from the system

Here is an example of my HTML code: <input type='file' multiple/> <?php for($i=0;$i<5; $i++) { ?> <div class="img-container" id="box<?php echo $i ?>"> <button style="display: none;" type="submit" cl ...

Tips and tricks for retaining the collapsed state upon reloading Bootstrap 5

Just diving into the world of bootstrap and javascript. How do I save the collapsed state to make sure it stays even after refreshing the page? <p> <button class="btn btn-primary" type="button" data-bs-toggle="collapse&q ...

What methods are available for utilizing a runtime variable that TypeScript is unaware of?

I am looking to implement a global variable in TypeScript that will be defined dynamically at runtime. This global variable is necessary for transferring configuration properties from the server-side language to JavaScript. My approach involves using TypeS ...

Unable to retrieve Objects from JSON

Here is a JSON object I received: [{"model": "pricing.cashflow", "pk": 1, "fields": {"value": 4.0, "date": "2016-09-09"}}, {"model": "pricing.cashflow", "pk": 2, "fields": {"value": 3.0, "date": "2016-09-01"}}, {"model": "pricing.cashflow", "pk": 3, "fiel ...

Why isn't Freichat displaying the name of the user who logged in?

After creating my own small social networking site, I decided to add a chat script called freichat. However, I am facing an issue where when a user logs in, their name appears as "Guest102" instead of their actual name. I am quite confused by this problem ...

Utilize the grid system from Bootstrap to style HTML div elements

I am working on my angular application and need help with styling items in a Bootstrap grid based on the number of elements in an array. Here's what I'm looking to achieve: If there are 5 items in the array, I want to display the first two items ...

Delving into the World of ReactJS Routing Components and Rendering

I recently developed a basic booking app consisting of 3 essential files - App.js, Booked.js (1st child), and Details.js (2nd child). My current dilemma involves attempting to access App.js for the purpose of deleting data using the 2nd child (Detail.js). ...

Steps for inserting a new entry at the start of a dictionary

My fetch method retrieves recordings from the database, but I need to prepend a new record to the existing data for frontend purposes. Can someone assist me with this? <script> export default { components: { }, data: function() { ...

Determining When the Collapse Transition in Material UI 5 is Complete

Snippet <Collapse in={expanded} onTransitionEnd={() => console.log('finished')} > <div>foo</div> </Collapse> Error Detection The callback function (onTransitionEnd) is not triggered af ...

Why is the defaultDate property not functioning properly in Material-UI's <DatePicker/> component with ReactJS?

I recently implemented the <DatePicker/> component from Material-UI ( http://www.material-ui.com/#/components/date-picker ) in my project. I encountered an issue while trying to set the defaultDate property to the current date on my computer, as it r ...

Show the tabulated outcomes of entries in a MySQL database and present them using ChartJs

My goal is to show the total number of rows stored in a MySQL Database and present these numbers using ChartJs. However, I am encountering issues with displaying the values correctly when retrieving data from my PHP Script. PHP Code Snippet for Counting R ...

Develop an interactive feature using React.js that allows users to manipulate the position of objects within a div

Looking to create a simple div with left and right buttons on either side that can shift the content in the center. An example of what I envision is shown here: Upon clicking the right arrow, the content should transition to this layout: Is there a Reac ...

Tips on successfully passing multiple keys and their associated HTML tag attributes in a React application

One of my links, specified with an a-tag, appears in this manner: <a href={ item.htmlReportUrl } target="_blank" rel="noopener noreferrer"> {item.htmlReportText}</a> The values for the href and the linktext are sourced from the following: ro ...

Using Chartjs to Dynamically Update Data from Database Values

I'm encountering some difficulties while attempting to refresh my Chartjs doughnut chart with data retrieved from my database. Below is the ajax call that I've implemented successfully: $.ajax({ url: "<!--#include virtual="../include/e ...

How can we capture and execute a function on the server in Next.js in response to a user's request for the index page (/)?

Is it possible to use a middleware function or another method in Next.js to check if a user is trying to access the home page? My goal is to intervene when a user tries to reach the home page. Intercepting a URL request is quite straightforward with Next. ...

How can I link to a different field in a mongoDB Schema without using ObjectID?

I have created two schemas for books and authors: const bookSchema = new mongoose.Schema({ title: String, pages: Number, description: String, author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' } }); const Book = mongoose.model ...

Error Encountered: Angular JS Throwing Unhandled Injection Error

I am having trouble validating the fields in my index.html and js files. I keep seeing errors, even after trying different versions of angular-route.min.js and angular.js. AngularJs | Basic Login Form <body ng-app="myApp"> ...