我想制作一个带有强制参数的路线。如果没有,它应该落入
$urlRouterProvider.otherwise("/home");
当前路线:
function router($stateProvider) {
$stateProvider.state("settings", {
url: "^/settings/{id:int}",
views: {
main: {
controller: "SettingsController",
templateUrl: "settings.html"
}
}
});
}
目前以下两条路线均有效:
有什么想法吗?
答案 0 :(得分:0)
使用state change start listener检查params是否通过:
$rootScope.$on('$stateChangeStart',
function (event, toState, toParams, fromState, fromParams) {
if(toState.name==="settings")
{
event.preventDefault(); //stop state change
if (toParams.id===undefined)
$state.go("home");
else
$state.go(toState, toParams);
}
});
答案 1 :(得分:0)
以下解决方案适用于ui-router 1.0.0:
.config(($stateProvider, $transitionsProvider) => {
//Define state
$stateProvider.state('verifyEmail', {
parent: 'portal',
url: '/email/verify/:token/:optional',
component: 'verifyEmail',
params: {
token: {
type: 'string',
},
optional: {
value: null,
squash: true,
},
},
});
//Transition hooks
$transitionsProvider.onBefore({
to: 'verifyEmail',
}, transition => {
//Get params
const params = transition.params();
//Must have token param
if (!params.token) {
return transition.router.stateService.target('error', {
type: 'page-not-found',
});
}
});
})
以上内容将强制:token
参数,:optional
参数可选。如果您尝试浏览到没有token参数的页面,它将无法转换并重定向到您的错误页面。但是,如果省略:optional
参数,则会使用默认值(null
)。
请记住在尾随的可选参数上使用squash: true
,否则如果省略URL中的尾随/
,您也会获得404。
注意:钩子是必需的,因为如果你使用尾部斜杠浏览到email/verify/
,ui-router会认为token参数是一个空字符串。因此,您需要在转换挂钩中进行额外处理以捕获这些情况。
答案 2 :(得分:0)
在我的应用中,我必须为很多路线制作必需的参数。所以我需要一种可重复使用且干燥的方法来做到这一点。
我在应用中定义constants
区域以访问全局代码。我也用于其他事情。
我在app配置时运行此notFoundHandler
。这是为处理错误设置路由器状态。它正在设置此错误路由的其他路由。您可以为缺少必需参数的时间定义不同的路径,但对我们而言,这被定义为与404体验相同。
现在在app运行时我还定义了一个stateChangeErrorHandler
,它将使用'required-param'字符串查找被拒绝的路由解析。
angular.module('app')
.constant('constants', constants)
.config(notFoundHandler)
.run(stateChangeErrorHandler);
// use for a route resolve when a param is required
function requiredParam(paramName) {
return ['$stateParams', '$q', function($stateParams, $q) {
// note this is just a truthy check. if you have a required param that could be 0 or false then additional logic would be necessary here
if (!$stateParams[paramName]) {
// $q.reject will trigger the $stateChangeError
return $q.reject('required-param');
}
}];
}
var constants = {
requiredParam: requiredParam,
// define other constants or globals here that are used by your app
};
// define an error state, and redirect to it if no other route matches
notFoundHandler.$inject = ['$stateProvider', '$urlRouterProvider'];
function notFoundHandler($stateProvider, $urlRouterProvider) {
$stateProvider
//abstract state so that we can hold all our ingredient stuff here
.state('404', {
url: '/page-not-found',
views: {
'': {
templateUrl: "/app/error/error.tpl.html",
}
},
resolve: {
$title: function () { return 'Page Not Found'; }
}
});
// redirect to 404 if no route found
$urlRouterProvider.otherwise('/page-not-found');
}
// if an error happens in changing state go to the 404 page
stateChangeErrorHandler.$inject = ['$rootScope', '$state'];
function stateChangeErrorHandler($rootScope, $state) {
$rootScope.$on('$stateChangeError', function(evt, toState, toParams, fromState, fromParams, error) {
if (error && error === 'required-param') {
// need location: 'replace' here or back button won't work on error page
$state.go('404', null, {
location: 'replace'
});
}
});
}
现在,在应用程序的其他地方,当我定义了一个路由时,我可以使它具有此路由解析所需的参数:
angular.module('app')
.config(routeConfig);
routeConfig.$inject = ['$stateProvider', 'constants'];
function routeConfig($stateProvider, constants) {
$stateProvider.state('app.myobject.edit', {
url: "/:id/edit",
views: {
'': {
template: 'sometemplate.html',
controller: 'SomeController',
controllerAs: 'vm',
}
},
resolve: {
$title: function() { return 'Edit MyObject'; },
// this makes the id param required
requiredParam: constants.requiredParam('id')
}
});
}
答案 3 :(得分:0)
我想指出不应该访问/settings
路径的任何问题,因为它不对应任何状态,除非你使用过继承状态(见下文)。
访问/settings/
路径时会发生实际问题,因为它会将空字符串(""
)分配给{{ 1}}参数。
以下是问题中的solution以下问题:
访问
id
路径,当状态为url/state_name/
时
它通过转换服务的onBefore挂钩( UI路由器1.x 或更高版本)工作,这可以防止转换到的状态缺少必需的参数。
为了声明某个状态的必需参数,我使用/state_name/:id
哈希,如下所示:
data
然后在.state('settings', {
url: '/settings/:id',
data: {
requiredParams: ['id']
}
});
中添加app.run
挂钩:
onBefore
您可以通过继承状态实现相同的逻辑:
transitionService.onBefore({}, function(transition) {
var toState = transition.to();
var params = transition.params();
var requiredParams = (toState.data||{}).requiredParams || [];
var $state = transition.router.stateService;
var missingParams = requiredParams.filter(function(paramName) {
return !params[paramName];
});
if (missingParams.length) {
/* returning a target state from a hook
issues a transition redirect to that state */
return $state.target("home", {alert: "Missing params: " + missingParams});
}
});
然后您需要将function router($stateProvider) {
$stateProvider
.state('settings', {
url: '/settings'
})
.state('settings.show", {
url: '/:id'
});
}
属性添加到父声明,以使abstract
路径无法访问。
以下是关于抽象的documentation所说的内容:
永远无法直接激活抽象状态。使用抽象状态为子状态提供继承的属性(url,resolve,data等)。
解决方案:
/settings
注意:这只解决了function router($stateProvider) {
$stateProvider
.state('settings', {
url: '/settings',
abstract: true
})
.state('settings.show", {
url: '/:id'
});
}
路径的问题,您仍需要使用 onBefore hook 解决方案,以便限制访问/settings
。