$ scope值不会在其他控制器中更新

时间:2016-02-20 09:13:53

标签: javascript angularjs

我在更新视图上的值时遇到问题。让我向您展示我的代码,并对正在发生的事情进行一些解释。我知道代码是乱七八糟的,因为我现在尝试了很多代码组合。

我有这个accCtrl控制器

controllers.accCtrl = function($scope, sessionFactory){
    sessionFactory.isLoggedIn().then(function(data){
        console.log(data.logged_in);
        $scope.loggedIn = data.logged_in;
    });
    $scope.logOut = function(){
        sessionFactory.logOutUser().then(function(data){
            $scope.loggedIn = data.logged_in;
        });
    }
}

控制台注销为false,此变量$ scope.loggedIn通过显示或隐藏登录,注册,我的个人资料和注销按钮来控制我的HTML

<div ng-controller="accCtrl">
    {{loggedIn}}
        <ul>
        <li ng-hide="loggedIn">
            <a href="#/login">
                <b>Login</b>
            </a>
        </li>
        <li ng-hide="loggedIn">
            <a href="#/register" >
                <b>Register</b>
            </a>
        </li>
        <li ng-show="loggedIn" >
            <a href="#/my_profile">
                <b >My profile</b>
            </a>
        </li>
        <li ng-show="loggedIn"> 
            <a ng-click="logOut()">
                <b>Log out</b>
            </a>
        </li>
    </ul>
</div>

现在用户尝试登录,点击登录按钮,显示登录表单。此登录功能以loginCtrl

编写
    controllers.loginCtrl = function($scope, $http, $location, $timeout, sessionFactory){
    $scope.loginUser = function () {
        $http({
            method: 'POST',
            url: $location.protocol() + '://' + $location.host() + '/server/api/users/login',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            data : $.param({
                username : $scope.username,
                password : $scope.password
            })
        }).success(function(data){
                sessionFactory.isLoggedIn().then(function(data){
                    $scope.loggedIn = data.logged_in;
                });
                window.location.href="/#/home";
        });
    };
}

成功登录后,他或她被重定向到主页上,但问题是帐户控制器中的$scope.loggedIn变量甚至没有更新,即使loginCtrl中的console.log(data.logged_in)被设置为{ {1}}

如果用户按下了注销按钮,一切正常,因为我在accCtrl中调用函数。所以唯一的问题是当用户登录时,因为他在另一个控制器中执行此操作。

此处还有我的sessionFactory,以防你如何检查用户是否被记录

true

我的app.js

app.factory('sessionFactory', ['$http', '$location', function($http, $location){
    var factory = {};

    factory.logOutUser = function(){
        return $http({
            method: 'GET',
            url: $location.protocol() + '://' + $location.host() + '/server/api/users/logout'
        }).then(function successCallback(response){
            return response.data;
        },function errorCallback(response) {
            console.log('error logging out: ' + response);
        });
    }
    factory.isLoggedIn = function(){
        return $http({
            method: 'GET',
            url: $location.protocol() + '://' + $location.host() + '/server/api/users/isLoggedIn'
        }).then(function successCallback(response){
            console.log(response.data);
            return response.data;
        },function errorCallback(response) {
            console.log('Checking login failed: ' + response);
        });
    }

    return factory;
}]);

我可能要实现一些手表或类似的功能,但我真的不知道如果你帮助我我会怎么样。

在图片中说明

显示登录和注册按钮 Working as expected

用户单击登录按钮并成功登录,但按钮未刷新,因为在loginCtrl中发生了操作,但按钮位于accCtrl

enter image description here

在浏览器中点击f5后,按钮会在accCtrl中正确更新。

enter image description here

TLTR

用户登录var app = angular.module('app', ['ngRoute', 'ngAnimate', 'ui.sortable', 'ngFileUpload']) app.config(function($routeProvider){ $routeProvider. when('/', {controller:'homeCtrl', templateUrl:'app/templates/home.html'}). when('/home', {controller:'homeCtrl', templateUrl:'app/templates/home.html'}). when('/contact', {controller:'contactCtrl', templateUrl:'app/templates/contact.html'}). when('/about_us', {controller:'aboutUsCtrl', templateUrl:'app/templates/aboutUs.html'}). when('/cookies', {controller:'cookiesCtrl', templateUrl:'app/templates/cookies.html'}). when('/faqs', {controller:'faqsCtrl', templateUrl:'app/templates/faqs.html'}). when('/register', {controller:'registerCtrl', templateUrl:'app/templates/register.html'}). when('/login', {controller:'loginCtrl', templateUrl:'app/templates/login.html'}). when('/my_profile', {controller:'myProfileCtrl', templateUrl:'app/templates/myProfile.html'}). when('/trade/:param1', {controller:'tradeCtrl', templateUrl:'app/templates/trade.html'}). when('/user/:param1', {controller:'userCtrl', templateUrl:'app/templates/user.html'}). when('/swap/:param1', {controller:'subCategoriesCtrl', templateUrl:'app/templates/subCategories.html'}). when('/swap/:param1/:param2', {controller:'products', templateUrl:'app/templates/products.html'}). when('/swap/:param1/:param2/:param3', {controller:'product', templateUrl:'app/templates/product.html'}). otherwise({ redirectTo: '/home'}); }); 后,我必须更新loginCtrl

中的$scope.loggedIn

如果您需要任何其他信息,请告诉我

2 个答案:

答案 0 :(得分:5)

出现问题是因为angularjs中的控制器只初始化一次,除非您将其设置为重新初始化。尝试提醒accCtrl中的内容,即使您多次导航到该页面,它也只会发出一次警报。点击ctrl+f5有效,因为它重新初始化了您的控制器。您只需使用$window.location.reload()重新初始化控制器即可。 $window.location.reload()的作用不仅是重新加载您的控制器,还重新加载您的服务。既然您正在使用ngRoute,我可以认为重新初始化您的控制器正在使用$window.location.reload();

.success(function(data){
                sessionFactory.isLoggedIn().then(function(data){
                    $scope.loggedIn = data.logged_in;
                });
                window.location.reload(); //the only workaround i could find with ngroute as for now.
                window.location.href="/#/home";
        });

然而,使用ui.Router$stateProvider为您提供了仅重新初始化控制器的选项,如下所示。

.state('home', {
    url: '/home',
    templateUrl: 'templates/home.html',
    controller: 'accCtrl',
    reload: true //will reload controller when state is being access
});

$state.transitionTo($state.current, {}, { reload: true, inherit: true, notify: true });

$state.go('.', null, { reload: true });

将解决重新初始化控制器的问题,这似乎是您现在问题的问题。

答案 1 :(得分:2)

好的,您在$scope.loggedIn变量上犯了2个错误。

1)您感到困惑,因为控制台为$scope.loggedIn记录了一个假值和一个真值;发生这种情况是因为promises是异步的,并且在您要求会话登录后代码继续运行。

sessionFactory.isLoggedIn().then(function(data){
    console.log(data);                     (2)
    $scope.loggedIn = data.logged_in;
    console.log($scope.loggedIn);          (3)
});
console.log($scope.loggedIn);              (1) <-- executes first before promise resolves
window.location.href="/#/home";

所以最后的顺序但是在执行日志中首先自然地产生错误,只要在promise开始执行之前没有记录用户。在promise解决后,它会产生数据并且为true。有关承诺的更多信息herehere

2)您正在使用ajax请求更改角度变量,并且当您从角度框架中更改范围时,需要通知角度。 One mechanism angular has for that使用$rootScope.$apply()或$ scope。$ apply()显式调用摘要周期。我建议你按照自己的意愿开展工作。如果你想在控制器中使用它,应该这样做:

$http({
    method: 'POST',
    url: $location.protocol() + '://' + $location.host() + '/server/api/users/login',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data : $.param({
        username : $scope.username,
        password : $scope.password
    })
}).success(function(data){
    ...
    $rootScope.$apply();
});