2016-10-03 60 views
0

在我的角度应用程序时,我一直在使用视图设置使用$腕表结合UI路由器:如何更新字段使用ControllerAs

.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已经呈现在用户界面中的绑定字段永远不会更新。我知道这是一个注入控制器$范围然后应用手表的候选人。但是,每当我这样做时,我都会得到一个摘要已经存在的角度错误。我试图将手表嵌入第二层,然后将其放在功能之外。嵌套在内部时会被忽略,当放置在承诺之外时,我会得到错误。

手表先前写为(注意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

您的代码或视图中可能存在错误。你不需要手表。发布一个完整的小例子,在一个plunkr中,重现这个问题。 –

+0

我不认为这是视图或代码中的错误,除了OIDC控制器在dom渲染后返回数据。我会尝试获得一个Plunker,但只要获得访问令牌和渲染数据,OIDC代码就无法从那里重现。向控制器添加一个vm.test =“hello”就是这样渲染的。绑定看起来是正确的。 – rlcrews

+0

从示例代码中很难判断问题的原因。我唯一的猜测是,如果'nav.message'是一个对象,那么您可能需要传递'true'作为$ watch的第三个参数,以便深入观察。 – mcranston18

回答

0

通过这个问题的工作,我可以看到错误被相关的消化周期,不能够以更新绑定的范围。通过类似的帖子看,我看到可能的答案,指出使用$timeout我不是一个风扇,因为这是一个异步调用,它感觉hokey使用超时,因为它可能不是100%可靠。然后我偶然发现了Ben Nadal的一篇博文,他解释了使用$scope.$evalAsync我不会进入完整的博客,但实质上: “$ scope。$ evalAsync()表达式被放置在一个”异步队列“中在每个$摘要迭代开始时刷新。“

鉴于我更新了我的代码现在看起来像:

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中的绑定更新。