Having difficulty updating the login button name with ng-show function

Once a user logs in, I set a boolean value to true and intend to update the login button status to display "Logout". Despite attempting to use ng-show, the functionality does not seem to be working properly.

App States:

myApp.config(function ($stateProvider, $urlRouterProvider) {

    // default route
    $urlRouterProvider.otherwise("/Home");
    var header = {
        templateUrl: 'commonViews/Header.html',
        controller: function ($scope) {
        }

    };
    var footer = {
        templateUrl: 'commonViews/Footer.html',
        controller: function ($scope) {
        }
    };
    // ui router states
$stateProvider
    .state('Home', {
        url: "/Home",
        views: {
            header: header,
            content: {
                templateUrl: 'views/HomePage.html',
                controller: function ($scope) {
                }
            },
            footer: footer
        }
    })
    .state('LoggedIn', {
        url: "/LoggedIn",
        views: {
            'header': header,
            'content': {
                templateUrl: 'views/LoggedIn.html',
                controller: function ($scope) {
                }
            },
            'footer': footer
        }
    });
});

User Service:

myApp.factory('UserService', function ($http, $localStorage, AuthenticationService) {
    return {
        logIn: function (email, password) {
            return $http.post('rs/loginResource/login', {email: email, password: password})
                    .then(function (data) {
                        AuthenticationService.isLogged = true;
                        alert("Authentication loggedIn inside login controller: " + AuthenticationService.isLogged);
                        return data;
                    })
                    .catch(function (error) {
                        console.log(error);
                    });
        },
        logOut: function () {
            if (AuthenticationService.isLogged) {
                AuthenticationService.isLogged = false;
                delete $localStorage.token;
            }
        }
    };
});

myApp.factory('AuthenticationService', function () {
    var auth = {
        isLogged: false
    };
    return auth;
});

Login Controller:

myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$sessionStorage', '$state', '$window', 'UserService', 'AuthenticationService', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state, $window, UserService, AuthenticationService)
    {
        $scope.token = "";
        $scope.$storage = $localStorage;
        $scope.loginForm = function (email, password) {

            if (email !== undefined && password !== undefined) {
                UserService.logIn(email, password).then(function (response) {
                    $localStorage.token = response.data.token;
                    if ($localStorage.token) {
                        $state.go('LoggedIn');
                        alert("scope loggedIn inside login controller: " + AuthenticationService.isLogged);
                    }
                }).catch(function (status, data) {
                    console.log(status);
                    console.log(data);
                });
            }

            $scope.logout = function logout() {
                UserService.logOut().success(function () {
                    $state.go('/');
                }).error(function (status, data) {
                    console.log(status);
                    console.log(data);
                });
            };
        };
    }]);

index.html:

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
    <head></head>
    <body>
        <div ui-view="header"></div>
        <div ui-view="content"></div>
        <div ui-view="footer"></div>
    </body>
</html>

Header HTML:

<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
        <div id="navbar" class="collapse navbar-collapse">
            <ul class="nav navbar-nav navbar-right">
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" ng-show="isLoggedIn" ng-click="logout()"><b>Logout</b></a>
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" ng-show="!isLoggedIn"><b>Login</b> <span class="caret"></span></a>
                    <ul id="login-dp" class="dropdown-menu">
                        <!---------------------------------Login Controller Here------------------------------------->
                        <li>
                            <div class="row"> 
                                <div class="col-md-12">
                                    <form class="form" role="form" method="post" ng-controller="loginController" ng-submit="loginForm(email, password)" accept-charset="UTF-8" id="login-nav">
                                        <div class="form-group">
                                            <label class="sr-only" for="exampleInputEmail2">Email address</label>
                                            <input type="email" class="form-control" ng-model="email" id="exampleInputEmail2" placeholder="Email address" required>
                                        </div>
                                        <div class="form-group">
                                            <label class="sr-only" for="exampleInputPassword2">Password</label>
                                            <input type="password" class="form-control" id="exampleInputPassword2" ng-model="password" placeholder="Password" required>
                                            <div class="help-block text-right"><a href="">Forget the password ?</a></div>
                                        </div>
                                        <div class="form-group">
                                            <button type="submit" class="btn btn-primary btn-block">Sign in</button>
                                        </div>
                                    </form>
                                </div>
                            </div>
                        </li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
</nav>

After a successful login, there seems to be an issue where the status momentarily changes to "Logout" before reverting back to "Login". It's unclear why this is happening. Any insights?

Answer №1

Include the AuthenticationService in your controller's scope,

$scope.AuthenticationService = AuthenticationService;

Then, make sure to remove $scope from your view/template

<ul class="nav navbar-nav navbar-right" ng-controller="loginController">
<li class="dropdown">
  <a href="#" class="dropdown-toggle" data-toggle="dropdown" ng-show="AuthenticationService.isLogged" ng-click="logout()"><b>Logout</b></a>
  <a href="#" class="dropdown-toggle" data-toggle="dropdown" ng-show="!AuthenticationService.isLogged"><b>Login</b> <span class="caret"></span></a>
</li>

Answer №2

Create an isLoggedIn() method and add it to the header controller:

myApp.config(function ($stateProvider, $urlRouterProvider) {

    // default route
    $urlRouterProvider.otherwise("/Home");
    var header = {
        templateUrl: 'commonViews/Header.html',
        controller: function ($scope, AuthenticationService) {
            $scope.isLoggedIn = function() {
                 return AuthenticationService.isLogged;
            });
        }

    };
    var footer = {
        templateUrl: 'commonViews/Footer.html',
        controller: function ($scope) {
        }
    };
    // ui router states

Then, in your header HTML file, utilize the newly created function:

 <a href="#" class="dropdown-toggle" data-toggle="dropdown" 
    ng-show="isLoggedIn()" ng-click="logout()"><b>Logout</b>
 </a>
 <a href="#" class="dropdown-toggle" data-toggle="dropdown" 
    ng-show="!isLoggedIn()">
    <b>Login</b> <span class="caret"></span>
 </a>

UPDATE

It's important to note that the ng-show directives may not be within the scope of your login controller. Make sure these functions querying the AuthenticationService.isLogged state are placed in the correct scope for the ng-show directives to function properly.

Answer №3

Looks like your code has a couple of issues:

  1. AuthenticationService.isLogged is not getting updated after a successful login with UserService.
  2. You don't need to include $scope in your templates, as any Angular expression will be resolved against the current scope in your HTML template.

It's recommended not to expose your services in the view layer. Instead, add a property like isLoggedIn on your scope to determine whether to display Login or Logout buttons.

myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$sessionStorage', '$state', '$window', 'UserService', 'AuthenticationService', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state, $window, UserService, AuthenticationService)
    {
        $scope.token = "";
        $scope.$storage = $localStorage;
        // new property to hold login status
        $scope.isLoggedIn = false;
        $scope.loginForm = function (email, password) {

            if (email !== undefined && password !== undefined) {
                UserService.logIn(email, password).then(function (response) {
                    $localStorage.token = response.data.token;
                    if ($localStorage.token) {
                        // cache the login status for use in other controllers
                        AuthenticationService.isLogged = true;

                        // update the scope for use in templates
                        $scope.isLoggedIn = true;
                        $state.go('LoggedIn');
                    }
                }).catch(function (status, data) {
                    console.log(status);
                    console.log(data);
                });
            }

            $scope.logout = function logout() {
                UserService.logOut().success(function () {
                   // cache the login status for use in other controllers
                    AuthenticationService.isLogged = false;

                   // update scope for use in templates
                    $scope.isLoggedIn = false;

                    $state.go('/');
                }).error(function (status, data) {
                    console.log(status);
                    console.log(data);
                });
            };
        };
    }]);

This way, in your templates, you can simply check for isLoggedIn as shown below

<ul class="nav navbar-nav navbar-right" ng-controller="loginController">
    <li class="dropdown">
        <a href="#" class="dropdown-toggle" 
                    data-toggle="dropdown" 
                    ng-show="isLoggedIn" 
                    ng-click="logout()">
          <b>Logout</b></a>
        <a href="#" class="dropdown-toggle"
                    data-toggle="dropdown" 
                    ng-show="!isLoggedIn">
          <b>Login</b> <span class="caret"></span>
        </a>
    </li>
</ul>

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 horizontal axis displays the hours from 12:00 to 12:55 instead of specific calendar dates

This script creates a highchart that includes 2 Y axes and 1 X axis: $('#main_chart').highcharts({ chart: { zoomType: 'xy' }, title: { text: 'Overview' }, xAxis: [{ ...

Once you exit the input field, a function activates to alter the background color of the input

Is there a way to trigger a function that changes the background color of an input field when the cursor leaves it? I tried implementing this solution, but it didn't work as expected. <!DOCTYPE html> <html> <body> Enter your name: & ...

Issue with AngularJS promise not returning any value in JavaScript

I have been attempting to perform a simple HTTP post in a unit test using Jasmine, but unfortunately, it is not functioning as expected. The application operates smoothly on the web, and I have individually tested various functions, all of which work seaml ...

Navigating Next.js: Mastering the art of localStorage Access

Currently, I am developing my first member area using next.js. My goal is to store some data in localStorage (such as token, expiresAt, userInfo), which will eventually be moved to an http-only cookie. The code below is generating the error: "LocalStorage ...

What is the best way to link CSS files from libraries that are downloaded using npm?

For instance, let's say I installed a package: npm install --save package and it gets saved in ./node_modules/package/ Inside that folder, there might be a directory named styles and within that directory, you could find style.css. How can I link ...

Sort the Bootstrap table based on the date column

I recently implemented the Bootstrap table plugin into my project, but I am facing issues with sorting dates correctly. Below is the code snippet I am using: <table class=" table-striped" id="table" data-toggle="table" ...

ScrollReveal.js won't function as intended

https://i.stack.imgur.com/SOQEk.png Looking to utilize the popular ScrollReveal.js created by Julian Lloyd (ScrollReveal) Despite following instructions from various sources, the script is not producing the intended effect. Steps taken to make it work: ...

Preventing the upload of empty images in an angular application

When selecting multiple images for upload, I sometimes need to make changes or delete the chosen images before actually uploading them. However, if any of the selected images have a size of 0B, I want to stop the upload process for all images, not just the ...

Testing the functionality of an Express Rest API with Mocha unit tests

I have just started diving into the world of unit testing. While I've been successful in running simple tests such as "adding two numbers and checking if the result is greater than 0", my goal now is to develop a REST API using Test-Driven Development ...

How can I run a TypeScript function within a JavaScript file?

I am working with a typescript file named file1.ts export function Hello(str: string) { console.log(str); } In addition, I have another file called index.js { require('./some.js'); } Furthermore, there is a script defined in the pack ...

The functionality of Bootstrap's JavaScript is dependent on the presence of jQuery - Reactjs framework

When attempting to combine bootstrap with reactjs, I encountered an issue with importing Bootstrap.js It seems that Bootstrap's JavaScript requires jQuery Below are some of the import statements I have tried: import $ from 'jquery'; imp ...

send document through ajax

Having some trouble with this task. Here is what I've managed to put together so far: <input id="newFile" type="file"/> <span style="background-color:orange;" onClick="newImage()">HEYTRY</span> I know it's not much progress. ...

What is the best way to sort a list with parent and child elements using Angular 2?

I have a tree structure in Angular 1 that allows me to filter the list at any level by typing in a textbox. Check out this demonstration to see it in action. Now, I am working on converting this functionality to Angular 2 and aiming for the desired output ...

Tips for running a React custom hook selectively or within a specific function

I have created a unique custom hook to handle user redirection to the edit page. While on the index page, users can duplicate and delete items. The issue arises when deleting an item triggers the custom hook to redirect back to the edit page. I am looking ...

What is the best method for purging a previously stored variable from the cache when making an Ajax call and simultaneously passing a

I am encountering an issue with variable loading during the ajax call. Upon clicking, I pass a variable to the ajax call which then sends the value to a PHP script. The data obtained is from: rnc.csv DLRNC01 DLRNC02 DLRNC03 DLRNC04 DLRNC05 DLRNC06 DLR ...

A tutorial on how to switch classes between two tabs with a click event in Vue.js

I am having an issue with my spans. I want to implement a feature where clicking on one tab changes its color to red while the other remains gray. I have tried using class binding in my logic but it's not working. How can I solve this problem and make ...

Currying in React - Understanding the Handler

Can anyone explain to me how this currying works in the example provided? I understand the name argument, but how does the event work in this scenario? <TextField placeholder="Name" InputLabelProps={{ shrink: true, ...

Streaming data from a third-party API using WebSockets to distribute it to various subclients

In our data-driven application, the backend continuously pulls data from a third-party server and sends it to the frontend clients via websockets. The problem arises when multiple clients connect, resulting in the same data being fetched multiple times unn ...

Forward user to a new page following successful login utilizing angular.js router and PHP

I am in need of assistance. I am looking to implement a page redirection after a user logs in using Angular.js with PHP as the backend. I have written some code, but it seems to be not functioning correctly. Below is an explanation of my code. index.htm ...

Attempting to execute a synchronous delete operation in Angular 6 upon the browser closing event, specifically the beforeunload or unload event

Is there a way to update a flag in the database using a service call (Delete method) when the user closes the browser? I have tried detecting browser close actions using the onbeforeunload and onunload events, but asynchronous calls do not consistently wor ...