2015-08-24 48 views
4

我正在使用Angular UI路由器(非常新的版本),我試圖更新搜索參數,而不是重新加載整個頁面。我想要$ watch $ stateParams,但手錶無法使用我的設置。爲了清楚起見,當我使用transitionTo()時,我希望更新URL,並且我希望$ stateParams被更新,$ watch被激發到$ stateParams,但是我不希望整個控制器再次運行。 reloadOnSearch:false阻止控制器再次運行,但具有停止觸發$ watch的副作用,或者看起來如此。反正這裏是我的代碼

$ stateProvider配置:

$urlRouterProvider.otherwise("/search"); 

$stateProvider 
    .state('search', { 
     url: "/search?locationtext&method", 
     templateUrl: "templates/searchResults.tpl.html", 
     controller: 'SearchResultsCtrl as searchResults', 
     reloadOnSearch : false 
    }) 

按鈕單擊處理程序:

$state.transitionTo($state.current, {locationtext: 'london'}, { 
    location : true, 
    reload: false, 
    inherit: false, 
    notify: true 
}); 

$看國家PARAMS:

$scope.stateParams = $stateParams; 

$scope.$watchCollection('stateParams', function(){ 
    $log.info("State params have been updated", $scope.stateParams); 
}); 

這是正在發生的事情:

1)首次加載狀態時,手錶會觸發並且狀態列將記錄到控制檯。

2)當我點擊按鈕,狀態被轉換和URL說#/搜索?locationtext =倫敦

3)手錶是不是在這一點上發射,雖然執行console.log顯示, $ state.params已更新

4)如果我點擊瀏覽器後退按鈕,位置文本=倫敦從URL中刪除,但手錶不會再觸發。

不知道我在做什麼錯在這裏。我假設我已經正確設置了手表,否則在控制器第一次加載時它不會啓動?

任何想法將不勝感激。

編輯:

我還增加了以下

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){ 
    console.log("$stateChangeStart", $rootScope.stateParams); 

}); 

但該事件甚至沒有開火,儘管URL變化和$ state.params作爲transitionTo後不同( );

編輯2:

我已經通過拖網的代碼,它好像reloadOnSearch設置爲false意味着,如果你只改變搜索參數,然後什麼也沒有發生,即使網址變更的過渡沒有按不會發生,$ stateChangeStart事件不會被廣播。

這不是我所期待的。我期待着所有這些發生,但控制器不會被重新加載。因此,現在我正在尋找一種方法來更改搜索參數並監視更改,以便我可以更新搜索結果。它看起來像Angular UI路由器沒有辦法做到這一點,因爲你得到一個控制器重新加載或沒有事件。

+0

點擊處理程序是如何綁定的?它是否在'$ digest'循環之外? (由非Angular事件,或setTimeout,或類似的東西引起的?)'$ state.transitionTo'不會觸發'$ apply'本身,所以如果是這種情況,你必須包裝它。 – DRobinson

+0

它由Angular UI分頁控件觸發,我認爲它使用ng-click模板。 – jonhobbs

+0

是的,那絕對是用ng-click包裹的,應該沒問題... – DRobinson

回答

8

問題是$stateParams不是$stateParams。他們可能看起來很相似,但顯然他們不是。

我的意思是,如果你手動刪除angular-ui-router源代碼如下行,你的觀察家會觸發:

var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params); 

Line 3534,內置分配; SRC /狀態Line 1385。 。JS爲未構建版本)

的替代方法除去線是使用angular.copy如本文件中其他地方使用:

var _stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params); 
copy(_stateParams, $stateParams); // This project has a short-hand for angular.copy 

無可否認,這是一個不完整的答案,因爲我不知道爲什麼會這樣。也許這是angular-ui-router中的一個錯誤,也許是由設計造成的。 您最好的選擇可能是迴應關於空$stateParams(這些可在https://github.com/angular-ui/ui-router/search?q=stateParams+&type=Issues)找到的許多開放門票之一,或者如果您認爲您有額外的信息,請創建一個。

在此期間,您可以通過觀看$state.params使你的代碼的工作,而不是:

$scope.$watchCollection(function(){ 
    return $state.params; 
}, function(){ 
    $log.info("State params have been updated", $scope.stateParams); 
}); 

編輯:一些測試代碼一起玩:http://plnkr.co/edit/0UqUzZDSfMtPf3bSjBS7?p=preview

在此plunker,您可以更改html中包含-updated版本的angular-ui-router以查看刪除該行實際上使兩種類型的觀察者都能正常工作。

+0

我不得不承認,我不明白所有這些,但$ state.params上使用$ watchCollection似乎工作。我現在可以轉換狀態(儘管完全轉換不會發生),並在使用後退按鈕時監視URL更改,即使是從不同的服務器頁面(例如,聯繫我們>搜索)。我實際上並不需要狀態轉換,因爲我不希望控制器重新加載。我可以獲取所有URL參數的好處,並在URL更改時更新我的​​搜索結果。完美,非常感謝。 – jonhobbs

+0

爲什麼這隻適用於作爲函數的$ stateParams的第一個參數?我嘗試了'$ watchCollection(「$ state.params)」,...'但沒有奏效。 –

+0

我的猜測是'$ state'只是一個變量(注入/一個參數),它不是'$ scope'的屬性。使用String觀察僅查看調用它的範圍對象的屬性。 – DRobinson