无法使用 ng-show 更改登录按钮的名称

Posted

技术标签:

【中文标题】无法使用 ng-show 更改登录按钮的名称【英文标题】:Unable to change the name of login button using ng-show 【发布时间】:2016-04-13 22:14:07 【问题描述】:

我在用户登录后将布尔值设置为 true,并且我想将登录按钮状态更新为注销。我尝试使用 ng-show 但显然它不起作用。

州:

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
        
    );
);

用户服务:

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;
);

登录控制器:

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>

标题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>

用户登录后,它会在瞬间将状态更改为注销,然后再次返回登录状态。我不知道出了什么问题?

【问题讨论】:

【参考方案1】:

AuthenticationService 添加到控制器的范围内,

$scope.AuthenticationService = AuthenticationService;

并从您的视图/模板中删除 $scope

<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>

【讨论】:

没用。将 AuthenticationService 添加到范围将如何解决我的问题。我猜使用$scope.AuthenticationService.isLogged 也是一样的 你有 2 个问题。一是您不能在模板中使用$scope(例如,您不说ng-click="$scope.logout()"...您说ng-click="logout()")。解决第一个问题后,您将遇到的问题是 AuthenticationService 尚未在 $scope 上定义,并且在添加范围之前无法从视图访问。 我将AuthenticationService 设置为您所说的范围,但它不起作用。仍然显示登录按钮而不是注销 啊。我在视图中省略了 isLogged 函数的括号。查看我更新的答案(我刚刚将ng-show="AuthenticationService.isLogged" 更改为ng-show="AuthenticationService.isLogged()")。现在应该可以工作了。 isLogged 不是我的userService 中的函数,但让我试试看【参考方案2】:

在您的标头控制器中放置一个isLoggedIn() 函数:

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

并在您的标题 HTML 中使用该功能:

 <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>

更新

您的登录控制器范围是标头控制器范围的子级。您的 ng-show 指令不在您的登录控制器的范围内。通过将查询AuthenticationService.isLogged 状态的函数放在正确的范围内,ng-show 指令应该可以正常工作。

【讨论】:

我删除了这个答案,因为@Arkantos 似乎在帮助你。但既然你坚持在这里。我认为它会解决您的显示/隐藏问题,但登录后登录表单仍然存在。 它可以工作,但有一个问题 - 当我刷新页面时,按钮变回登录 这就是我不愿意回答你的问题的原因。你的代码有很多问题。您的登录控制器将某些内容放在本地存储中,但您的 AuthenticationService 不检查本地存储。您使用范围变量来更改模板而不是登录状态来更改模板。看起来你举了两个例子,只是以一种奇怪的方式混合它们。您的代码非常脆弱。改变一件事,另一件事就会崩溃。 嗯好的。 AuthenticationService 没有检查本地存储(包含 JWT 令牌),因为它已经有效,否则它将返回 false。我很困惑,我是角度的初学者。我想我应该手动使用state.go 来更改路线。 stateProvider 将如何处理使用状态更改模板?【参考方案3】:

您的代码中有 2 个问题

    AuthenticationService.isLogged 使用 UserService 成功登录后未更新 您不需要在模板中包含 $scope,因为您在 HTML 模板中传递的任何 Angular 表达式都将针对当前范围进行解析。

我建议不要将您的服务公开到您的视图层。只需在您的范围内添加一个属性isLoggedIn,它将决定是否显示登录或注销按钮。

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);
                );
            ;
        ;
    ]);

有了这个,在你的模板中,你可以像下面这样检查isLoggedIn

<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>

【讨论】:

你是对的。在视图层中公开服务不是一个好习惯。让我试一试 我猜问题出在各州。 header.html 是一个单独的文件,其中有登录/注销按钮。我正在使用 ui-router 注入 header.html 文件,这可能是问题吗? 我认为问题在于当您进入LoggedIn 状态时,您正在更新headerfootercontent。因此,您的 HTML 将再次加载并再次初始化您的控制器,因为范围内的 isLoggedIn 属性被重置 正是我猜测的状态,有些事情是错误的。如何不重新加载页眉和页脚?并有范围值? 理想情况下,您的登录表单应该在内容视图中,而不是在标题视图中,并且仅在 LoggedIn 状态下更新内容视图。我建议您这样做,但是有一种解决方法可以使用身份验证服务中的缓存值重新填充范围,更新了我对此的答案

以上是关于无法使用 ng-show 更改登录按钮的名称的主要内容,如果未能解决你的问题,请参考以下文章

计算机名称更改后,软件无法连接SQL数据库!急求!

无法让 ng-hide 和 ng-show 使用令牌

win10为啥我无法更改账户名称

无法使用 ionic2 在设备上获取上一页名称

如何通过动态单击按钮来更改选项卡标题名称?

ng-show无法处理窗口滚动