在我的角度应用程序中,我使用ui-router设置了视图:
.state('search',
{
url: '/',
views: {
'navigation': {
templateUrl: '/app/views/navbartemplate.html',
controller: 'navigationController',
controllerAs: 'nav'
},
'content': {
templateUrl: '/app/views/search.html',
controller: 'searchController',
controllerAs: 'search'
}
}
})
我正在使用来自Identity Server 3的声明,并使用访问令牌和身份声明将用户信息传递给客户端。由于这是一个角度应用程序,因此使用回调检索声明。它接收访问令牌,然后传递该令牌以获取作为异步回调的身份。这全部使用OIDC令牌管理器进行管理。在导航控制器中,我尝试将用户的值(名字姓氏)映射到导航视图中来自此回调的字段。
//get user information
// no id token or expired => redirect to get one
if (vm.mgr.expired) {
vm.mgr.redirectForToken();
} else {
vm.mgr.oidcClient.loadUserProfile(vm.mgr.access_token)
.then(function(userInfoValues) {
dataService.setItem(userInfoValues);
}).then(function() {
vm.profile = dataService.getItem();
checkAdmin(vm.profile.sys_admin);
vm.message = "Welcome, " + vm.profile.given_name + " " + vm.profile.family_name;
$log.info(vm.profile.sys_admin);
$log.info(vm.message);
});
}
我可以通过日志看到属性已设置,但由于DOM已经呈现UI中的绑定字段,因此永远不会更新。我知道这是注入控制器$ scope的候选者,然后应用手表。然而,每当我这样做时,我得到角度误差,消化已经存在。我试图将手表嵌入第二个.then承诺内,并将其置于功能之外。嵌套在里面时会被忽略,当放在promise之外时我会得到错误。
该手表之前曾被写为(注意nav是视图中的ControllerAs):
$scope.$watch('nav.message', function(){
checkAdmin(vm.profile.sys_admin);
vm.message = "Welcome, " + vm.profile.given_name + " " + vm.profile.family_name;
});
更新:经过一些额外的测试后,我将该功能移出了第二个承诺,看起来更像是这样:
var loadData = function() {
checkAdmin(vm.profile.sys_admin);
vm.message = "Welcome, " + vm.profile.given_name + " " + vm.profile.family_name;
$log.info(vm.profile.sys_admin);
$log.info(vm.message);
}
//get user information
// no id token or expired => redirect to get one
if (vm.mgr.expired) {
vm.mgr.redirectForToken();
} else {
vm.mgr.oidcClient.loadUserProfile(vm.mgr.access_token)
.then(function(userInfoValues) {
dataService.setIqItem(userInfoValues);
vm.profile = dataService.getIqItem();
}).then(loadData);
}
我意识到这些功能做了同样的事情,但我发现点击屏幕上的其他按钮来改变CSS主题(导致页面回发/重新渲染的任何内容)会更新绑定,我会看到它们出现在UI中的值中。这看起来好像它与角度代码完成之前的DOM渲染有关,并且范围没有更新。我将在明天尝试深度观察方法,看看是否可以纠正它。
我仍然很好奇如何在Oidc经理返回用户身份后如何更新消息字段?观看Deepwatch或其他一些方法。我已经看到用户使用超时的SO帖子,但这似乎是错误的或不可靠的。这应该是服务而不是视图控制器中的某些东西吗?任何想法都赞赏。
提前致谢
答案 0 :(得分:0)
解决这个问题我可以看到错误与摘要周期有关,并且范围无法更新绑定。通过类似的帖子,我看到可能的答案表明使用$timeout
我不是这个的粉丝,因为这是一个异步调用,并且使用超时感觉很好,因为它可能不是100%可靠。然后我偶然发现了Ben Nadal的一篇博客文章,他在那里解释了$scope.$evalAsync
的用法我不会进入完整的博客,但实质上是:
" $ scope。$ evalAsync()表达式放在"异步队列中#34;在每个$ digest迭代开始时刷新。"
鉴于我更新了我的代码,现在看起来像:
if (vm.mgr.expired) {
vm.mgr.redirectForToken();
} else {
vm.mgr.oidcClient.loadUserProfile(vm.mgr.access_token)
.then(function(userInfoValues) {
$scope.$evalAsync(function() {
dataService.setItem(userInfoValues);
vm.profile = dataService.getItem();
checkAdmin(vm.profile.sys_admin);
vm.message = "Welcome, " + vm.profile.given_name + " " + vm.profile.family_name;
});
});
}
现在评估已提升,以便更新UI中的绑定。