Angular:通过服务或更好的方法更新不同的控制器

时间:2013-12-10 21:24:27

标签: javascript angularjs

我有一个UserService

angular.module('mango.services', [])
    .factory('UserService', function() {
        var user = {
            id: null,
            name: 'anonymous.'
        };
        function getUser(){
            return user;
        }
        function setUser(val){
            user = val;
        }
        return {
            getUser: getUser,
            setUser: setUser,
        }
});

一个NavbarController

.controller('NavbarController', ['$scope','$location','UserService', function($scope, $location, UserService){
    $scope.isActive = function (viewLocation) {
        return viewLocation === $location.path();
    };
    $scope.username = UserService.getUser().name;
}])

和一个UserController,我有registerUser和loginUser函数。

.controller('UserController', ['$scope', '$http', 'UserService', function($scope, $http, UserService) {
   $scope.loginUser = function(){
        $http.post('/api/1.0/user/authenticate', $scope.user)
            .success(function(data,status,headers,config){
                if (data["valid"] === true) {
                    UserService.setUser(data.user);
                } else {
                    $scope.flashes = data.flashes;
                    $scope.user.password = "";
                }
             })
}

和HTML

        <li ng-switch="username">
            <a ng-class="{ active: isActive('/user/login')}" href="#/user/login" ng-switch-when="anonymous."><i class="fa fa-sign-in"></i> Sign in</a>
            <a ng-class="{ active: isActive('/user/logout')}" href="#/user/logout" ng-switch-default><i class="fa fa-sign-out"></i> Sign out</a>
        </li>

正如您所看到的,如果data.valid为true,我正在尝试设置UserService的用户。

服务器正在返回一个有效的json对象。

但NavbarController中的用户名值仍为“匿名”。

我在JS方面不是很有经验,但我读过有关广播和观看的内容。我相信这可能是正确的方法。但也许有一个更好的。

我相信为什么它不起作用是因为工厂返回一个单身人士。但是,使用工厂毫无意义。

基本上我想要的是,如果凭证有效,则设置user.name user.id client-app-wide。稍后它应该通过“检查客户端用户是否有效”服务。我的会话cookie已加密。但这超出了问题的范围。

我现在需要的是从UserController设置应用程序或者更确切地说是NavbarController的用户数据。我该怎么做,所以它也更新DOM aka ng-switch获得不同的值。

3 个答案:

答案 0 :(得分:2)

它无法正常工作,因为您没有创建某种类型的绑定:使用$scope.username = UserService.getUser().name,您可以在该时刻获得用户名(即anonymous)并永久保留它。其中一个方法是使用手表。在NavbarController中,将以前的代码替换为:

$scope.$watch(
    function() {
        return UserService.getUser().name;
    },
    function(newval) {
        $scope.username = newval;
    }
);

这会在每个摘要周期中通过函数调用生成应用程序。这个函数调用并不慢,所以没关系。

如果您不想要这种开销,您也可以使用事件来完成。在NavbarController中:

$scope.username = UserService.getUser().name;
$scope.on("loggedIn", function(event, newUserName) {
    $scope.username = newUserName;
});

在UserController中(将$rootScope添加到依赖项):

if (data["valid"] === true) {
    UserService.setUser(data.user);
    $rootScope.$broadcast("loggedIn", data.user);
}

答案 1 :(得分:1)

您确实需要$watchusernameNavbarController而不是UserService同步$scope.username = UserService.getUser().name;,而$scope.username只设置$scope.$watch( function () { return UserService.getUser().name; }, function (newVal) { $scope.username = newVal; } ); 的初始值初始化Controller时{1}}:

User

工厂确实设计为整个应用程序的单例,这是您应该保存应用程序的状态的地方(即您的模型,如NavbarControll模型)。控制器是短暂的,每次创建模板时都会重新创建。

但是,如果你有一个长寿命的控制器(就像你的sync),那么在服务器和控制器之间维护$watch的责任在于使用models的程序员。

在某些情况下,当需要控制器间通信(不一定涉及{{1}})时,广播消息很有用。

答案 2 :(得分:0)

  • 您可以使用相同的方法而不使用$ watch。

我编写了一个简短的函数,可以将数据放入Object而无需替换它。 您可以在服务中使用它。这样你就不需要使用手表了。您可以使用Angular的正常摘要循环。 例如,看到这个简单的控制器&amp;服务:

演示:JSFidde - http://jsfiddle.net/y09kx7f7/1/ 断言测试

<强>控制器:

#SACRED-HEART-COLLEGE {
    font-family:"Trajan Pro Regular";
    font-size: 24px;
    color: rgb(30, 30, 117);

    position: absolute;
    top: 0;
}

每次更改用户名时,控制器将自动进行无人值守!

<强>服务

app.controller('dem',function($scope,me){
    $scope.user=me.user;   // {name:'user name'}
})

我写的cloneInto函数:

.factory('me',function($timeout){
    var obj={}
    obj.user={name:'hello'}
    $timeout(function(){  //Example of change the data
        newUser={name:'israel'}
        cloneInto(obj.user,newUser)
    },1000)
    return obj
})