How to set required route parameters

I want to make a route with a required parameter. If not, he should fall in

$urlRouterProvider.otherwise("/home");

Current route:

 function router($stateProvider) { $stateProvider.state("settings", { url: "^/settings/{id:int}", views: { main: { controller: "SettingsController", templateUrl: "settings.html" } } }); } 

Both of the following routes are currently in effect:

Any ideas?

+5
source share
5 answers

Use state change start listener to check if parameters have been passed:

  $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); } }); 
0
source

For ui-router 1.0.0, the following solution is valid:

 .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', }); } }); }) 

The above :token parameter :token required, and the :optional parameter is optional. If you try to go to a page without a token parameter, this will lead to a failure of the transition and redirect to the error page. However, if you omit the :optional parameter, it will use the default value ( null ).

Remember to use squash: true for the final optional parameters, because otherwise you will also get 404 if you skip / in the URL.

Note: a hook is required because if you go to email/verify/ with a trailing slash, ui-router will assume that the token parameter is an empty string. Therefore, to capture these cases, you will need additional processing to intercept the transition.

0
source

In my application, I needed to specify the necessary parameters for many routes. So I needed a reusable and harsh way to do this.

I define the scope of constants in my application to access global code. I use other things as well.

I run this notFoundHandler at the time of setting up the application. This is the router status setting for error handling. It sets a route along the path to this error. You can define a different route when the required parameter is missing, but for us it was defined as the same as the 404 experience.

Now when I start the application, I also define stateChangeErrorHandler , which will look for the rejected route solution with the string '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' }); } }); } 

Now, in another place of the application, when I have a specific route, I can make it have the required parameter when resolving this route:

 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') } }); } 
0
source

I would like to point out that there should not be any problems accessing the /settings path, since it does not correspond to any state if you have not used inherited states (see below).

The actual problem occurs when accessing the path /settings/ , because it will assign an empty string ( "" ) to the id parameter.

If you have not used inherited conditions

Here is the solution in plunker for the following problem:

access to the path /state_name/ when there is a state with url /state_name/:id

Decision explanation

It works through the onBefore hook ( UI router 1.x or higher) transition service, which prevents the transition to states with missing required parameters.

To declare what parameters are needed for the state, I use the data hash as follows:

 .state('settings', { url: '/settings/:id', data: { requiredParams: ['id'] } }); 

Then in app.run add hook 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}); } }); 

If you used legacy conditions

You can implement the same logic through inherited states:

 function router($stateProvider) { $stateProvider .state('settings', { url: '/settings' }) .state('settings.show", { url: '/:id' }); } 

you need to add the abstract property to the parent declaration to make the /settings path unavailable.

Decision explanation

This is what abstract state documentation describes :

The abstract state can never be directly activated. Use an abstract state to provide inherited properties (url, resolve, data, etc.) For child states.

Decision:

 function router($stateProvider) { $stateProvider .state('settings', { url: '/settings', abstract: true }) .state('settings.show", { url: '/:id' }); } 

Please note: this only solves the problem with /settings path, and you still need to use the onBefore hook solution to also restrict access to /settings/ .

0
source

it is not very well documented, but you can have the required and optional parameters, as well as parameters with default values.

Here is how you can set the required parameters:

 function router($stateProvider) { $stateProvider.state("settings", { url: "^/settings/{id:int}", params: { id: {} }, views: { main: { controller: "SettingsController", templateUrl: "settings.html" } } }); } 

I never used params with curly braces, just with a semicolon, like this url: "^/settings/:id" , but from what I read, this is equivalent.

For other types of parameters, please see the other half of my answer here: AngularJS UI Router - change URL without rebooting

Please note that when I added this answer, I had to create a ui-router from the source code, but I read that the functionality was added to the official release.

-1
source

Source: https://habr.com/ru/post/1215321/


All Articles