我的代码大部分都在工作,但我很难看到更改从控制器中的User对象传播。
我要做的是构建一个User
服务来管理我网站上当前用户的所有方面。例如:User.login()
,User.logout()
,User.currentUser
,User.isLoggedIn
等。
请记住,我仍然是Angular和ngResource的新手: - )。
感觉我在这里需要$rootScope.$apply()
或类似的东西?
/**
* The $resource factory.
*/
angular.module('myApp.services', ['ngResource'])
.factory('User', ['$resource', '$http', function($resource, $http) {
var User,
anonymousUser,
currentUser,
isLoggedIn;
anonymousUser = { uid: 0, pass: null, name: 'Anonymous' };
currentUser = angular.copy(anonymousUser);
isLoggedIn = false;
User = $resource('api/user/:verb', {}, {
login: {
method: 'POST',
params: { verb: 'login' },
isArray: false,
// (Ab)using the transformResponse callback to update currentUser
// and isLoggedIn when necessary.
transformResponse: $http.defaults.transformResponse.concat([
function (data, headersGetter) {
if (angular.isObject(data) && angular.isObject(data.user)) {
currentUser = data.user;
isLoggedIn = true;
}
// TODO: Flipping to anonymous user when a login error occurs. Double check if this logic is sound.
else {
currentUser = angular.copy(anonymousUser);
isLoggedIn = false;
}
return data;
}
])
},
logout: {
method: 'POST',
params: { verb: 'logout' },
isArray: false, // eg: [true] transformed to { result: true }
// (Ab)using the transformResponse callback to update currentUser
// and isLoggedIn when necessary.
transformResponse: $http.defaults.transformResponse.concat([
function (data, headersGetter) {
if (angular.isArray(data) && data.length > 0) {
if (data[0] === true) {
currentUser = angular.copy(anonymousUser);
isLoggedIn = false;
}
return { result: data[0] };
} else {
// TODO: Deal with indeterminate state here. Is the user logged in still or not?
// TODO: Return error.
return { result: false };
}
}
])
}
});
// FIXME: Adding extra properties onto our $resource here. These ARE visible in the controller but bindings and $watch don't work on them.
User.isLoggedIn = isLoggedIn;
User.currentUser = currentUser;
// FIXME: Attempting to bring these objects under the purview of Angular but this isn't helping.
$rootScope.isLoggedIn = isLoggedIn;
$rootScope.currentUser = currentUser;
return User;
}]);
/**
* The controller.
*/
angular.module('myApp.page', [])
.controller('NavbarCtrl', ['$scope', 'User', function ($scope, User) {
// These work, but are not dynamically updated when User.login() and User.logout() are called.
$scope.currentUser = User.currentUser;
$scope.isLoggedIn = User.isLoggedIn;
// FIXME: $watch is only called once, changes in User.login() and User.logout() do not invoke $watch here.
$scope.$watch('currentUser', function (newVal, oldVal) {
console.log([newVal, oldVal], 'Watching curentUser');
}, true);
}])
答案 0 :(得分:1)
这不是棱角分明的方式。如果你想创建服务 - 创建服务,角度有这方面的工具,你可以阅读关于此的信息here。工厂不应该有逻辑。因此,在您的服务方法中创建登录,注销等,并借助$ http发送请求到您的服务器。
答案 1 :(得分:0)
也许你可以尝试使用原型。但我仍然不知道这是一个真正的角度方式
.factory('User', ['$resource', ($resource) ->
user = $resource API_PATH + "/user", {},
update: {method: 'PUT'}
user.prototype.login = ->
blah_blah()
user.prototype.logout = ->
blah_blah()
user
然后使用它:
user = new User()
user.login();
答案 2 :(得分:0)
是否有更好/更多的Angular方法来构建它?
这完全是意见。我认为如果你创建它以允许组件可读和可重用,那么这就是" angular"办法。我有类似的设置,但我将" isLoggedIn"进入一个单独的工厂。 (我将在下面说明这一点)。
$ resource工厂的自定义属性是否可能?
不确定你的意思。但如果你的意思是创建自己的方法,如$ login(),那么答案是肯定的。
感觉好像我需要一个$ rootScope。$ apply()或者类似的吗?
您可以使用回调设置$ scope变量。我的方法使用$ resource对象的实例,所以它可能与你的有点不同:
将用户分成不同的服务:
.factory('UserSession', function(){
var user = {
"name": '',
"isLoggedIn": false
};
return user
});
JUST MY OPINION 简化了$ resource factory:
.factory('User', ['$resource', '$http', function($resource, $http) {
return $resource('api/user/:verb', {}, {
login: {
method: 'POST',
params: { verb: 'login' },
isArray: false
},
logout: {//}
});
}]);
在控制器中,注入'用户'和' UserSession',并向$ resource实例添加回调:
.controller('whatever', ['$scope', 'User', 'UserSession', function($scope, user, sess){
var logged = sess.isLoggedIn;
if (!logged){
var u = new user();
u.$login({},function(data){ // I forgot the "$" originally - oops.
$scope.currentUser = data.user.name; // whatever the object looks like;
sess.isLoggedIn = true;
sess.name = data.user.name;
// now UserSession can be used in other parts of the app
// may need $scope.$broadcast if other controllers are currently using this data
}
}
}])
同样,这只是意见。 :)