服务变量未在控制器中更新 [英] Service variable not updating in controller
问题描述
我有一个位于 ng-view 之外的 NavbarCtrl.我有一个登录控制器,它与服务对话以让用户登录.用户登录后,我希望导航栏更新为用户的电子邮件地址.但是,在我的一生中,一旦用户登录,我似乎无法使用加载到身份验证"服务中的数据更新 Navbar 范围.
这是我的主要 index.html:
<div class="container" ng-view>
还有我的服务:
.factory('Auth', function($resource) {无证认证=假;无功用户 = {};返回 {isAuthenticated: 函数 () {返回已验证;},获取用户:函数(){返回用户;},登录:函数(登录用户,回调){用户 = {email:'email@email.com'}已认证 = 真;回调(真);//为简洁起见,实际登录代码}}})
还有我的登录和导航栏控制器:
function LoginCtrl($scope, $location, Auth) {$scope.login = function() {Auth.login($scope.user, function(success) {if(success) $location.path('/dashboard');//console.log(Auth.getUser())});}}功能 NavbarCtrl($scope, Auth) {//认为这应该有效$scope.user = Auth.getUser();//使用 $watch 实验失败$scope.$watch(Auth.isAuthenticated(),function() {$scope.user = Auth.getUser()})//点击刷新按钮是我可以让它工作的唯一方法$scope.refresh = function() {$scope.user = Auth.getUser()}}
根据我的研究,我会认为 $scope.user = Auth.getUser();会工作,但它不是,我完全不知道如何在用户登录时更新我的导航栏.在此先感谢您的帮助.
更新:好吧,你每天都在学习新东西......只需删除 ()
即可查看函数的结果:
$scope.$watch(Auth.isAuthenticated, function() { ... });
在这个小提琴中,注意当 $scope.isAuthenticated
的值发生变化时,'watch1' 和 'watch3' 是如何再次触发的.
因此,这是监视对服务定义的原始值的更改的通用技术:
- 定义返回原语(值)的 API/方法
- $观察那个方法
要观察在服务上定义的对象或数组的变化:
- 定义返回(引用)对象/数组的 API/方法
- 在服务中,注意只修改对象/数组,不要重新赋值.
例如,不要这样做:user = ...;
相反,这样做:angular.copy(newInfo, user)
或这样:user.email = ...
- 通常您会为该方法的结果分配一个本地 $scope 属性,因此 $scope 属性将是对实际对象/数组的引用
- $观察范围属性
示例:
$scope.user = Auth.getUser();//因为user是一个对象的引用,如果你改变了对象//在服务中(即,您不重新分配它),$scope.user 将//同样改变.$scope.$watch('user', function(newValue) { ... }, true);//上面,$watch 的第三个参数设置为 'true' 进行比较//相等而不是引用.如果您使用的是 Angular 1.2+//使用 $watchCollection() 代替:$scope.$watchCollection('user', function(newValue) { ... });
<小时>
原答案:
要观察一个函数的结果,你需要给 $watch 传递一个封装了这个函数的函数:
$scope.$watch( function() { return Auth.isAuthenticated() }, function() { ... });
小提琴.在小提琴中,注意当 $scope.isAuthenticated
的值发生变化时,只有 'watch3' 会第二次触发.(它们最初都触发,作为 $watch 初始化的一部分.)
I have a NavbarCtrl that is outside of ng-view. I have a login controller that talks to a service to get a user logged in. Once the user is logged in, I want the Navbar to update with the user's email address. However for the life of me, I can't seem to get the Navbar scope to update with the data that is loaded in to my "Auth" service once the user is logged in.
This is my main index.html:
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="#">Brim</a>
<div class="pull-right" ng-controller="NavbarCtrl">
<div ng-click="refresh()">hello</div>
{{ user.email }}
</div>
</div>
</div>
</div>
<div class="container" ng-view>
And my service:
.factory('Auth', function($resource) {
var authenticated = false;
var user = {};
return {
isAuthenticated: function () {
return authenticated;
},
getUser: function() {
return user;
},
login: function(loginUser, callback) {
user = {email:'email@email.com'}
authenticated = true;
callback(true);
//actual code for logging in taken out for brevity
}
}
})
And my Login and Navbar controllers:
function LoginCtrl($scope, $location, Auth) {
$scope.login = function() {
Auth.login($scope.user, function(success) {
if(success) $location.path('/dashboard');
//console.log(Auth.getUser())
});
}
}
function NavbarCtrl($scope, Auth) {
//thought this should work
$scope.user = Auth.getUser();
//experimenting unsuccessfully with $watch
$scope.$watch(Auth.isAuthenticated(),function () {
$scope.user = Auth.getUser()
})
//clicking on a refresh button is the only way I can get this to work
$scope.refresh = function() {
$scope.user = Auth.getUser()
}
}
From my research I would have thought that $scope.user = Auth.getUser(); would work, but it's not and I'm at a complete loss as to how how I can get my Navbar updated when a user is logged in. Thanks in advance for any help.
Update: well, you learn something new every day... just remove the ()
to watch the results of a function:
$scope.$watch(Auth.isAuthenticated, function() { ... });
In this fiddle, notice how 'watch1' and 'watch3' both trigger a second time when the value of $scope.isAuthenticated
changes.
So, this is the general technique to watch for changes to a primitive value that is defined on a service:
- define an API/method that returns (the value of) the primitive
- $watch that method
To watch for changes to an object or array that is defined on a service:
- define an API/method that returns (a reference to) the object/array
- In the service, be careful to only modify the object/array, don't reassign it.
E.g., don't do this:user = ...;
Rather, do this:angular.copy(newInfo, user)
or this:user.email = ...
- normally you'll assign a local $scope property the result of that method, hence the $scope property will be a reference to the actual object/array
- $watch the scope property
Example:
$scope.user = Auth.getUser();
// Because user is a reference to an object, if you change the object
// in the service (i.e., you do not reassign it), $scope.user will
// likewise change.
$scope.$watch('user', function(newValue) { ... }, true);
// Above, the 3rd parameter to $watch is set to 'true' to compare
// equality rather than reference. If you are using Angular 1.2+
// use $watchCollection() instead:
$scope.$watchCollection('user', function(newValue) { ... });
Original answer:
To watch the results of a function, you need to pass $watch a function that wraps that function:
$scope.$watch( function() { return Auth.isAuthenticated() }, function() { ... });
Fiddle. In the fiddle, notice how only 'watch3' triggers a second time when the value of $scope.isAuthenticated
changes. (They all trigger initially, as part of $watch initialization.)
这篇关于服务变量未在控制器中更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!