2016-10-03 64 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中的綁定更新。