Angular 路由器 - $watch 状态参数不工作
Angular Router - $watch state params not working
我正在使用 Angular UI 路由器(最新版本)并且我正在尝试更新搜索参数而不是重新加载整个页面。我想 $watch $stateParams,但手表无法使用我的设置。
为清楚起见,当我使用 transitionTo() 时,我希望更新 URL 并且我希望更新 $stateParams 并在 $stateParams 上触发 $watch,但我不不想让整个控制器再次成为 运行。 reloadOnSearch: false 再次从 运行ning 停止控制器,但具有阻止 $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
});
$观察状态参数:
$scope.stateParams = $stateParams;
$scope.$watchCollection('stateParams', function(){
$log.info("State params have been updated", $scope.stateParams);
});
这是正在发生的事情:
1) 首次加载状态时,手表会触发并将状态参数记录到控制台。
2) 当我单击按钮时,状态发生转换并且 url 显示 #/search?locationtext=london
3) 虽然 console.log 显示 $state.params 已更新
,但此时手表未触发
4) 如果我点击浏览器后退按钮,locationtext=london 将从 URL 中删除,但手表不会触发。
不确定我做错了什么。我假设我已经正确设置了手表,否则它不会在第一次加载控制器时触发?
如有任何想法,我们将不胜感激。
编辑:
我还添加了以下内容
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
console.log("$stateChangeStart", $rootScope.stateParams);
});
但事件甚至没有触发,尽管 url 发生了变化并且 $state.params 在 transitionTo();
之后有所不同
编辑 2:
我一直在浏览代码,似乎将 reloadOnSearch 设置为 false 意味着如果您只更改搜索参数那么什么也不会发生,即使 URL 更改不会发生转换并且$stateChangeStart 事件未广播。
这不是我所期待的。我期待所有这一切都会发生,但不会重新加载控制器。所以现在我正在寻找一种方法来更改搜索参数并观察更改,以便我可以更新我的搜索结果。看起来 Angular UI 路由器无法执行此操作,因为您要么重新加载控制器,要么没有事件。
问题是 $stateParams
不是 $stateParams
。它们可能看起来相似,但显然它们并非如此。
我的意思是,如果您从 angular-ui-router
源代码中手动删除以下行,您的观察者将触发:
var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params);
(unbuilt 版本 src/state.js 的Line 3534, of the built distributable; Line 1385。)
删除该行的替代方法是使用 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 以包含 angular-ui-router 的 -updated
版本,以查看删除该行实际上使两者观察者的类型可以正常工作。
我正在使用 Angular UI 路由器(最新版本)并且我正在尝试更新搜索参数而不是重新加载整个页面。我想 $watch $stateParams,但手表无法使用我的设置。
为清楚起见,当我使用 transitionTo() 时,我希望更新 URL 并且我希望更新 $stateParams 并在 $stateParams 上触发 $watch,但我不不想让整个控制器再次成为 运行。 reloadOnSearch: false 再次从 运行ning 停止控制器,但具有阻止 $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
});
$观察状态参数:
$scope.stateParams = $stateParams;
$scope.$watchCollection('stateParams', function(){
$log.info("State params have been updated", $scope.stateParams);
});
这是正在发生的事情:
1) 首次加载状态时,手表会触发并将状态参数记录到控制台。
2) 当我单击按钮时,状态发生转换并且 url 显示 #/search?locationtext=london
3) 虽然 console.log 显示 $state.params 已更新
,但此时手表未触发4) 如果我点击浏览器后退按钮,locationtext=london 将从 URL 中删除,但手表不会触发。
不确定我做错了什么。我假设我已经正确设置了手表,否则它不会在第一次加载控制器时触发?
如有任何想法,我们将不胜感激。
编辑:
我还添加了以下内容
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
console.log("$stateChangeStart", $rootScope.stateParams);
});
但事件甚至没有触发,尽管 url 发生了变化并且 $state.params 在 transitionTo();
之后有所不同编辑 2:
我一直在浏览代码,似乎将 reloadOnSearch 设置为 false 意味着如果您只更改搜索参数那么什么也不会发生,即使 URL 更改不会发生转换并且$stateChangeStart 事件未广播。
这不是我所期待的。我期待所有这一切都会发生,但不会重新加载控制器。所以现在我正在寻找一种方法来更改搜索参数并观察更改,以便我可以更新我的搜索结果。看起来 Angular UI 路由器无法执行此操作,因为您要么重新加载控制器,要么没有事件。
问题是 $stateParams
不是 $stateParams
。它们可能看起来相似,但显然它们并非如此。
我的意思是,如果您从 angular-ui-router
源代码中手动删除以下行,您的观察者将触发:
var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params);
(unbuilt 版本 src/state.js 的Line 3534, of the built distributable; Line 1385。)
删除该行的替代方法是使用 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 以包含 angular-ui-router 的 -updated
版本,以查看删除该行实际上使两者观察者的类型可以正常工作。