The issue with AngularJS Routing is that it fails to refresh the menu items when the URL and views are being

My current project involves implementing token-based authentication using the MEAN stack. The goal of my application is to display different menu items based on whether a user is logged in or not. When there is no token present, the menu should show options for Home, Signin, and Signup. Once a user is logged in and a token is generated, the menu should update to show Home, Me, and Logout. While the server-side functionality for Signin, Signup, and Logout is functioning correctly with proper URL redirection and view rendering, I am facing an issue with the dynamic updating of the Menu items. The menu only refreshes when I manually trigger a page refresh. I am seeking assistance in resolving this issue.

Below are snippets from my Index.html file (Includes omitted for brevity):

<body ng-app="app">
    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation" data-ng-controller="authCtrl">
       <!-- data-ng-controller="authCtrl" -->
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#/">Angular Restful Auth</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a ng-href="#/">Home</a></li>
                    <li data-ng-show="token"><a ng-href="#/me">Me</a></li>
                    <li data-ng-hide="token"><a ng-href="#/login">Signin</a></li>
                    <li data-ng-hide="token"><a ng-href="#/register">Signup</a></li>
                    <li data-ng-show="token"><a ng-click="logout()">Logout</a></li>                    
                </ul>
            </div><!--/.nav-collapse -->
        </div>
    </div>
    <div class="container" ng-view="">
    </div> <!-- /container -->
    </body>

The accompanying app.js script contains the configuration details:

'use strict';

var app = angular.module('app', ['ngRoute', 'authControllers', 'authServices']);
var authControllers = angular.module('authControllers', []);
var authServices = angular.module('authServices', []);

var options = {};
options.api = {};
//dev URL
options.api.base_url = "http://localhost:3000";

app.config(['$locationProvider', '$routeProvider',
function($location, $routeProvider) {
  $routeProvider.
  when('/', {
    templateUrl: 'partials/home.html',
    controller: 'authCtrl'
  }).
  when('/login', {
    templateUrl: 'partials/signin.html',
    controller: 'authCtrl'
  }).
  when('/register', {
    templateUrl: 'partials/signup.html',
    controller: 'authCtrl'
  }).
  when('/me', {
    templateUrl: 'partials/me.html',
    controller: 'authCtrl'
  }).
  otherwise({
    redirectTo: '/'
  });
}]);
app.config(['$httpProvider', function ($httpProvider) {
  $httpProvider.interceptors.push('TokenInterceptor');
}]);
app.run(function($rootScope, $location, $window, AuthenticationService) {
  $rootScope.$on("$routeChangeStart", function(event, nextRoute, currentRoute) {
    //redirect only if both isAuthenticated is false and no token is set
    if (nextRoute != null && nextRoute.access != null && nextRoute.access.requiredAuthentication
      && !AuthenticationService.isAuthenticated && !$window.sessionStorage.token) {
        $location.path("/login");
      }
    });
  });

Lastly, the authControllers.js file includes the necessary controller functions:

authControllers.controller('authCtrl', ['$scope', '$location', '$window', 'UserService', 'AuthenticationService',
function authCtrl($scope, $location, $window, UserService, AuthenticationService) {
  //Admin User Controller (login, logout)
  $scope.logIn = function logIn(username, password) {
    if (username !== undefined && password !== undefined) {
      UserService.logIn(username, password).success(function(data) {
        AuthenticationService.isLogged = true;
        $window.sessionStorage.token = data.token;
        $location.path("/me");
      }).error(function(status, data) {
        console.log(status);
        console.log(data);
      });
    }
  }
  $scope.token = $window.sessionStorage.token;
  $scope.me = function() {
    UserService.me(function(res) {      
      $scope.myDetails = res;
    }, function() {
      console.log('Failed to fetch details');
      $rootScope.error = 'Failed to fetch details';
    })
  };
  $scope.logout = function logout() {
    if (AuthenticationService.isAuthenticated) {
      UserService.logOut().success(function(data) {
        AuthenticationService.isAuthenticated = false;
        delete $window.sessionStorage.token;
        $location.path("/");
      }).error(function(status, data) {
        console.log(status);
        console.log(data);
      });
    }
    else {
      $location.path("/login");
    }
  }
  $scope.register = function register(username, password, passwordConfirm) {
    if (AuthenticationService.isAuthenticated) {
      $location.path("/me");
    }
    else {
      UserService.register(username, password, passwordConfirm).success(function(data) {
        $location.path("/login");
      }).error(function(status, data) {
        console.log(status);
        console.log(data);
      });
    }
  }
}]);

Answer №1

$scope.accessToken = $window.sessionStorage.token;

Make sure you update your scope variable each time and call apply explicitly if you are not in the digest loop to bind the token to the storage property.

Answer №2

After experimenting with various methods, I discovered a more efficient approach to handle global changes in one shot. By injecting $rootScope into my controller and assigning the SessionStorage token value to it, I was able to streamline the process without having to update $scope variables in multiple locations.

authControllers.controller('authCtrl', ['$rootScope','$scope', '$location', '$window', 'UserService', 'AuthenticationService',
function authCtrl($rootScope,$scope, $location, $window, UserService, AuthenticationService) {
$rootScope.token = $window.sessionStorage.token;
}]);

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

Customize the color of the label and underline in a Reactjs material-ui TextField when the field input

https://i.stack.imgur.com/oJ2ah.png <TextField id="standard-full-width" label="Password" style={{ margin: 8 }} fullWidth margin="normal" placeholder="*******" /> Struggling to understand how to modify the color of the label ...

Is there a way to access the content of a drop-down menu in JavaScript besides using ".value"?

Trying to create a table with rows that change dynamically but columns that are fixed. There's a drop-down menu whose content is based on an xml file. When I use .value to access the current content of my drop-down menu, it works fine in Firefox but n ...

The image file that was uploaded from a React Native iOS application to Azure Blob Storage appears to be corrupted or incomplete as it is not

Struggling to develop a feature in a React Native mobile app where users can upload and crop their profile picture, then store it in Azure blob storage. I encountered difficulty with implementing react-native-fs as many resources recommended it, but I kep ...

Error with Ant Design Autocomplete functionality when searching for a number

I am currently using ant design to develop a more advanced autocomplete component that will display data from multiple columns. In this particular scenario, I have two columns named tax_id and legal_name that users can search by. Everything works smoothly ...

how to dynamically update a button's text using Vue.js

I have a challenge where I need to dynamically change the text of a button based on whether a value is true or false. Below is the code snippet that I have been working on: <button class="btn btn-primary table-button" type="button&quo ...

A new value was replaced when assigning a JSON value inside a loop

Is there a way to generate a structure similar to this? { "drink": { "2": { "name": "coke", "type": "drink" }, "3": { "name": "coke", "type": "drink" } }, "food": ...

Angular: Intercept Drag and Drop Actions

I am utilizing angular-ui to create a sortable list using "drag and drop" functionality, and it is functioning perfectly. Here is an example of how it works: index.html <ul ui-sortable ng-model="list"> <li ng-repeat="item in list" class="it ...

"Can you guide me on how to display a React component in a

I have a function that loops through some promises and updates the state like this: }).then((future_data) => { this.setState({future_data: future_data}); console.log(this.state.future_data, 'tsf'); }); This outputs an array o ...

Issue with Bootstrap-vue pagination navigation not functioning correctly (unexpectedly refreshes upon clicking a page)

I recently updated my website's gallery pagination by following a helpful guide. However, I encountered a problem where clicking on a new page number refreshes the entire webpage, unlike the smooth transition shown in the tutorial. This is not the beh ...

JavaScript generating HTML code causing malfunctions

I have been attempting to implement the IN Place Editing feature using JQuery. Below is the code snippet editinplace.js $(document).ready(function() { //When div.edit me is clicked, run this function $("div.editme").click(function() { // ...

Locate a specific option that matches the value of the selected data-status and set it as "selected" using jQuery

Currently, I am facing an issue where I need to load 2 separate ajax responses into a select dropdown. The select dropdown will have a data-status attribute, and my goal is to loop through the options to find the one that matches the value of the select da ...

Embed Text inside an HTML Canvas

As someone who is relatively new to working with html canvas, I am having a bit of trouble when it comes to containing text within the canvas area. Specifically, I am pulling text from a textarea and displaying it on the canvas, but it seems to stay as one ...

Make sure to attach a resize event handler just once

I am working with a widget that inserts a div element into the DOM. This div requires some JavaScript to handle the resize event effectively. Here's the issue: The widget may be added multiple times on the same page, but I want to avoid adding re ...

Using TypeScript to send state through history.push({...})

I recently utilized the history.push method to redirect to a specific URL while passing along some information through the included state. Here's how I implemented it: const history = useHistory() history.push({ pathname: '/someurl/', ...

Using props as classnames in next.js applications

I am currently attempting to create a dynamic header for each page of my app that changes color based on the current page. Here is my approach: <Header className="headerBitcoin"></Header> My goal is to have the same header component ...

Guide to adding up the radio button values with Javascript

The tutorials I have reviewed include: How might I calculate the sum of radio button values using jQuery? How to find a total sum of radio button values using jQuery/JavaScript? How might I calculate the sum of radio button values using jQuery? Unfortu ...

What is the most efficient way to loop through an array and send each item to a method, ensuring that all methods are executed synchronously?

I need to make a request method call that retrieves its own body as an array, which is one item within another array. To achieve this, I have to iterate over the parent array and pass each of its items to the request method for a new server request. I tr ...

Can you explain the significance of this error message that occurs when attempting to execute a node.js script connected to a MySQL database?

const mysql = require('mysql'); const inquirer = require('inquirer'); const connection = mysql.createConnection({ host: "localhost", port: 8889, user: "root", password: "root", database: "bamazon" }) connection.conn ...

Can someone explain to me the best way to utilize the variable $scope.compdata within the

I am encountering an issue where I cannot access the variable $scope.compdata outside of the controller. Can someone help me with this? Thanks in advance. var compdata; $scope.fetchCompanies = function() { var deferred = $q.defer(); Company.ge ...

Ways to retrieve the value of a concealed element without any activation signal

In my project, I've created a slider that dynamically shows different forms one by one. Each form contains a hidden element with a specific value that I need to retrieve (using its class) every time a new form is displayed. This way, I can use that el ...