AngularJS UI路由器 – 更改url,无需重新加载状态
目前我们的项目是使用默认的$routeProvider
,我使用这个“黑客”来更改url
无需重新加载页面:
services.service('$locationEx', ['$location', '$route', '$rootScope', function($location, $route, $rootScope) { $location.skipReload = function () { var lastRoute = $route.current; var un = $rootScope.$on('$locationChangeSuccess', function () { $route.current = lastRoute; un(); }); return $location; }; return $location; }]);
并在controller
$locationEx.skipReload().path("/category/" + $scope.model.id).replace();
我正在考虑用ui-router
replacerouteProvider
来嵌套路由,但不能在ui-router
find它。
是否有可能 – 与angular-ui-router
?
为什么我需要这个? 我举个例子来解释一下:
clicking
保存后,创build新类别的路线是/category/new
我显示success-alert
,我想改变路线/category/new
到/caterogy/23
(23 – 是存储在db中的新项目的id)
只要你可以使用$state.transitionTo
而不是$state.go
。 $state.go
内部调用$state.transitionTo
但自动将选项设置为{ location: true, inherit: true, relative: $state.$current, notify: true }
。 你可以调用$state.transitionTo
并设置notify: false
。 例如:
$state.go('.detail', {id: newId})
可以被replace
$state.transitionTo('.detail', {id: newId}, { location: true, inherit: true, relative: $state.$current, notify: false })
编辑:正如fraczbuild议它可以简单地是:
$state.go('.detail', {id: newId}, {notify: false})
好的,解决 🙂 Angular UI路由器有这个新的方法,$ urlRouterProvider.deferIntercept() https://github.com/angular-ui/ui-router/issues/64
基本上是这样的:
angular.module('myApp', [ui.router]) .config(['$urlRouterProvider', function ($urlRouterProvider) { $urlRouterProvider.deferIntercept(); }]) // then define the interception .run(['$rootScope', '$urlRouter', '$location', '$state', function ($rootScope, $urlRouter, $location, $state) { $rootScope.$on('$locationChangeSuccess', function(e, newUrl, oldUrl) { // Prevent $urlRouter's default handler from firing e.preventDefault(); /** * provide conditions on when to * sync change in $location.path() with state reload. * I use $location and $state as examples, but * You can do any logic * before syncing OR stop syncing all together. */ if ($state.current.name !== 'main.exampleState' || newUrl === 'http://some.url' || oldUrl !=='https://another.url') { // your stuff $urlRouter.sync(); } else { // don't sync } }); // Configures $urlRouter's listener *after* your custom listener $urlRouter.listen(); }]);
我认为这种方法目前只包括在angular度ui路由器的主版本,一个可选参数(这也是很好,顺便说一句)。 它需要从源代码克隆和构build
grunt build
文档也可以从源代码中获取
grunt ngdocs
(他们被内置到/ site目录)// README.MD中的更多信息
似乎有另一种方式来做到这一点,dynamic参数 (我没有使用)。 许多信贷nateabele。
作为一个旁注,这里是Angular UI路由器的$ stateProvider中的可选参数 ,我将它与上面的组合使用:
angular.module('myApp').config(['$stateProvider', function ($stateProvider) { $stateProvider .state('main.doorsList', { url: 'doors', controller: DoorsListCtrl, resolve: DoorsListCtrl.resolve, templateUrl: '/modules/doors/doors-list.html' }) .state('main.doorsSingle', { url: 'doors/:doorsSingle/:doorsDetail', params: { // as of today, it was unclear how to define a required parameter (more below) doorsSingle: {value: null}, doorsDetail: {value: null} }, controller: DoorsSingleCtrl, resolve: DoorsSingleCtrl.resolve, templateUrl: '/modules/doors/doors-single.html' }); }]);
这样做可以解决一个状态,即使其中一个参数丢失。 SEO是一个目的,另一个可读性。
在上面的例子中,我想把doorsSingle作为一个必需的参数。 不清楚如何定义这些。 它适用于多个可选参数,所以不是一个真正的问题。 讨论在这里https://github.com/angular-ui/ui-router/pull/1032#issuecomment-49196090
花了很多时间在这个问题上,这是我的工作
$state.go('stateName',params,{ // prevent the events onStart and onSuccess from firing notify:false, // prevent reload of the current state reload:false, // replace the last record when changing the params so you don't hit the back button and get old params location:'replace', // inherit the current params on the url inherit:true });
这个设置解决了以下问题:
- 从
.../
到.../123
更新URL时,不会调用训练控制器两次 - 在导航到另一个状态时,训练控制器不再被调用
状态configuration
state('training', { abstract: true, url: '/training', templateUrl: 'partials/training.html', controller: 'TrainingController' }). state('training.edit', { url: '/:trainingId' }). state('training.new', { url: '/{trainingId}', // Optional Parameter params: { trainingId: null } })
调用状态 (来自任何其他控制器)
$scope.editTraining = function (training) { $state.go('training.edit', { trainingId: training.id }); }; $scope.newTraining = function () { $state.go('training.new', { }); };
培训控制员
var newTraining; if (!!!$state.params.trainingId) { // new newTraining = // create new training ... // Update the URL without reloading the controller $state.go('training.edit', { trainingId : newTraining.id }, { location: 'replace', // update url and replace inherit: false, notify: false }); } else { // edit // load existing training ... }
我做了这个,但在很久以前的版本:UI路由器的v0.2.10像这样的东西::
$stateProvider .state( 'home', { url: '/home', views: { '': { templateUrl: Url.resolveTemplateUrl('shared/partial/main.html'), controller: 'mainCtrl' }, } }) .state('home.login', { url: '/login', templateUrl: Url.resolveTemplateUrl('authentication/partial/login.html'), controller: 'authenticationCtrl' }) .state('home.logout', { url: '/logout/:state', controller: 'authenticationCtrl' }) .state('home.reservationChart', { url: '/reservations/?vw', views: { '': { templateUrl: Url.resolveTemplateUrl('reservationChart/partial/reservationChartContainer.html'), controller: 'reservationChartCtrl', reloadOnSearch: false }, 'viewVoucher@home.reservationChart': { templateUrl: Url.resolveTemplateUrl('voucher/partial/viewVoucherContainer.html'), controller: 'viewVoucherCtrl', reloadOnSearch: false }, 'addEditVoucher@home.reservationChart': { templateUrl: Url.resolveTemplateUrl('voucher/partial/voucherContainer.html'), controller: 'voucherCtrl', reloadOnSearch: false } }, reloadOnSearch: false })
如果您只需要更改url,但是防止更改状态:
更改位置(如果要在历史logging中replace,请添加.replace):
this.$location.path([Your path]).replace();
防止redirect到你的状态:
$transitions.onBefore({}, function($transition$) { if ($transition$.$to().name === '[state name]') { return false; } });
我不认为你需要这个ui路由器。 可用于$ location服务的文档在第一段中说:“… $ location的变化反映到浏览器地址栏中”。 它稍后继续说:“它不能做什么?当浏览器URL被改变时,它不会导致整个页面重新加载。”
所以,考虑到这一点,为什么不简单地改变$ location.path(因为该方法是一个getter和setter),如下所示:
var newPath = IdFromService; $location.path(newPath);
该文档注意到path始终应该以正斜杠开始,但是如果缺less,则会添加它。