我有一个带有navbar指令和基本注册/登录功能的应用。我希望在用户登录后更改导航栏上的一些字词(从#39;注册/登录'到#39;退出')但我无法确定用最好的(甚至是一种)方法做到这一点。我已经尝试将我想要更改的变量/绑定的值设置为在用户登录时更新的工厂,但这不起作用,并且指令不会更新新价值。
我的代码附在下面,特定的解决方案是值得赞赏的,但并非真的有必要,如果有人能指出我正确的方向,如何做到这一点将非常有帮助。
我尝试过的解决方案:
不幸的是,这些都不会导致指令变量动态更新。我觉得解决方案非常简单,但我无法想到我应该做些什么。
潜在解决方案:
navbar.html
<nav class="navbar navbar-static-top navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#/">
<span class="glyphicon glyphicon-star"></span> Home
</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-6">
<ul class="nav navbar-nav">
<li><a ui-sref="message">Message</a></li>
<li><a ui-sref="list">User List</a></li>
<li><a ui-sref="schedule">Schedule</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a ng-href="{{ vm.accountStatusLink }}">{{ vm.accountStatus }}</a></li>
</ul>
</div>
</div>
</nav>
navbar.directive.js
(function() {
'use strict';
angular
.module('app')
.directive('mainNavbar', mainNavbar);
mainNavbar.$inject = ['userFactory'];
function mainNavbar(userFactory) {
var directive = {
restrict: 'E',
templateUrl: 'app/components/navbar/navbar.html',
scope: {
creationDate: '='
},
controller: NavbarController,
controllerAs: 'vm',
bindToController: true
};
return directive;
function NavbarController() {
var vm = this;
// solution 1 (doesn't work)
vm.accountStatus = userFactory.userStatus;
vm.accountStatusLink = userFactory.userStatusLink;
// solution 2 (doesn't work)
//vm.accountStatus = userFactory.getUserStatus();
//vm.accountStatusLink = userFactory.getUserStatusLink();
}
}
})();
user.factory.js
(function() {
'use strict'
angular
.module('app')
.factory('userFactory', userFactory);
userFactory.$inject = ['$http', '$cookies'];
function userFactory($http, $cookies) {
var userStatusLink = '#/user/';
var userStatus = 'Sign Up / Log In';
var service = {
verifyUser: verifyUser,
storeUser: storeUser,
userStatusLink: userStatusLink,
userStatus: userStatus
};
return service;
/* verifyUser() snip */
function storeUser(user) {
$cookies.putObject('user', user); // stores user obj in cookies
userStatusLink = '#/signout/';
userStatus = 'Sign Out';
}
/* solution 2 getters
function getUserStatus() {
return userStatus;
}
function getUserStatusLink() {
return userStatusLink;
}
*/
}
})();
更新
userFactory.storeUser(user)
在.success
回调中异步发生:
$http.post('someurl').success(function(user) {
userFactory.storeUser(user);
});
答案 0 :(得分:1)
首先,登录和注销的显示值应该在指令范围内。该小部件(指令)应该是拥有登录/注销的所有表示的内容。
这听起来像你真的想在指令之间进行通信。这是人们常常被困住的常见问题。您可以在工厂中公开用户值并让指令监视更改,但这样做很昂贵,因为它占用了有限数量的手表中的一个。
指令之间传递数据的常见模式是使用事件。您的工厂或其他指令可以$rootScope.$emit('user-signed-in', userData)
。
这会在$ rootScope和所有父作用域上发出一个事件,但没有,所以它比$ broadcast更快。
然后您的指令会侦听事件$rootScope.on('user-signed-in', function(userData) {})
。
答案 1 :(得分:1)
您是否尝试过制作getUserStatusLink和getUserStatus方法,并将视图绑定到这些方法?
function userFactory($http, $cookies) {
...
var service = {
...
getUserStatusLink: function() {
return userStatusLink;
},
getUserStatus: function() {
return userStatus;
}
};
...
}
然后在你的NavBar控制器中:
function NavbarController() {
...
vm.accountStatusLink = userFactory.getUserStatusLink();
vm.accountStatus = userFactory.getUserStatus();
}
在userFactory中更新userStatusLink和userStatus时,这应该是您要做的事情。
<强>更新强>
由于异步调用storeUser()
方法,因此在设置新值时不会触发另一个摘要周期。因此,您应该使用$ timeout服务强制Angular执行摘要周期:
userFactory.$inject = [ ..., '$timeout'];
function userFactory( ..., $timeout) {
...
function storeUser(user) {
...
// forces Angular to perform a digest cycle, thus refreshing your view
$timeout(function() {
userStatusLink = '#/signout/';
userStatus = 'Sign Out';
});
}
...
}
更新2:
使用此实现工作jsFiddle。我包含了两种方法,因此您可以看到使用$ timeout而不使用$ timeout:http://jsfiddle.net/HB7LU/15366/
的区别我在一个地方引导你错了,更新控制器变量以直接访问方法:
function NavbarController() {
...
// remove the parens at the end of userFactory.getUserStatusLink();
vm.accountStatusLink = userFactory.getUserStatusLink;
// remove the parens at the end of userFactory.getUserStatus();
vm.accountStatus = userFactory.getUserStatus;
}
然后更新您的视图以实际调用方法:
<!-- add parens to view to make it actually call the methods -->
<li><a ng-href="{{ vm.accountStatusLink() }}">{{ vm.accountStatus() }}</a></li>
最终更新:
原来$ timeout是不必要的,因为Angular在$ http服务的成功回调中执行摘要循环。只需更新视图即可直接访问该方法就足以解决问题。
答案 2 :(得分:0)
您是否尝试复制链接并在布尔方法上使用ng-hide / ng-show来指示您的用户是否已登录?