How to define optional parameter using UI-Router without trailing slash as well?

2.8k views Asked by At

I was working on migration of my Angularjs code from ng-router to UI-Router. In my ng-router I have optional parameters however I realized that same easy way to support optional parameter is not supported in ui-router. Following is my routes from my existing ng-router module.

//Define routes for view  using ng-router
$routeProvider.
        when('/my-app/home/:userid?', {
            templateUrl: '/templates/partials/home/HomeView.html',
            controller: 'HomeViewController'
        })                   
        .when('/my-app/:productKey/:userid?', {
            templateUrl: '/templates/partials/productpage/ProductPageView.html',
            controller: 'ProductViewController'
        })
        .otherwise({redirectTo: '/my-app/home'});

Note: If you see ":userid" parameter is very smoothly implemented here as optional.

I tried following in ui-router however same is not working. I have gone through many post and it was suggested to duplicate the routes. I really don't want to duplicate as it will make code dirty.

//Set the default route

$urlRouterProvider.otherwise('/my-app/home');
//Define routes for view   (Please make sure the most matched pattern is define at top)
$stateProvider
        .state('viewallcards', {
            url: '/my-app/home/:userid',
            templateUrl: '/templates/partials/home/HomeView.html',
            controller: 'HomeViewController'
        })
        .state('productpage', {
            url: '/my-app/:productKey/:userid',
            templateUrl: '/templates/partials/productpage/ProductPageView.html',
            controller: 'ProductViewController'
        });

Here /my-app/home/ works however /my-app/home doesn't work. How to make it without trailing slash as well?

Also following post on same issue has surprised to me to know that this is not supported in ui-router. Is it still valid? Please help.

2

There are 2 answers

2
Radim Köhler On BEST ANSWER

There is a working example

We can use params : {} object to define the userid exactly as we need (i.e. ready to be omitted).

Check more details about params here:

Angular ui router passing data between states without URL

  $stateProvider
    .state('viewallcards', {
      url: '/my-app/home/:userid',
      params: { 
        userid: {squash: true, value: null }, // this will make both links below working:
        //         #/my-app/home
        //         #/my-app/home/
      },
      ...
    })
    .state('productpage', {
      url: '/my-app/:productKey/:userid',
      ...
    })

Check it in action here

2
nitsua On

By default, UI Router is in "strict mode" - where it differentiates between routes with a trailing slash and without. You can turn this off by disabling this mode:

How can I have my routes be activated when the url contains either a trailing slash or not?

Set strictMode to false in your config block:

$urlMatcherFactoryProvider.strictMode(false)

For older version of ui-router, add this snippet to your module's config function. It creates a rule on $urlRouterProvider that maps all urls that are missing a trailing slash to the same url but with the trailing slash appended.

Using this, it's best to define your optional parameters as URL parameters in the style of home?userid=foo, and set stuff that you always expect to see in the URL.

From the UI-Router's Wiki.