Case insensitivity with angularjs ui-router

12,103

Solution 1

Following the link in the comments to the original question, i was able to get the answer I needed.

Before my $stateProvider.state(......) routes I now have this piece of code:

$urlRouterProvider.rule(function ($injector, $location) {
       //what this function returns will be set as the $location.url
        var path = $location.path(), normalized = path.toLowerCase();
        if (path != normalized) {
            //instead of returning a new url string, I'll just change the $location.path directly so I don't have to worry about constructing a new url string and so a new state change is not triggered
            $location.replace().path(normalized);
        }
        // because we've returned nothing, no state change occurs
    });

Essentially it will toLowerCase() a url that isn't all lowercase already.

Once done, it replaces the url rather than redirects. Then carries on with matching a state.

Solution 2

You can now configure ui-router to be case insensitive directly. Here is how you can use it:

angular.module('main', ['ui.router']);

angular.module('main').config(['$urlMatcherFactoryProvider', '$stateProvider', '$urlRouterProvider',
  function($urlMatcherFactory, $stateProvider, $urlRouter) {
    $urlMatcherFactory.caseInsensitive(true);
    $urlMatcherFactory.strictMode(false);
    $stateProvider.state('foo', {
      url: '/foo',
      template: '<b>The Foo View</b>'
    });
    $stateProvider.state('bar', {
      url: '/bar',
      template: '<b>The Bar View</b>'
    });
    $stateProvider.state('nomatch', {
      url: '/nomatch',
      template: '<b>No match found View</b>'
    });

    $urlRouter.otherwise('/nomatch');
  }
]);

In the latest release (0.2.11), this is broken. A fix has been pushed already that can be seen at Github. So, currently, the best solution is to clone ui-router and build the head of master manually. Alternatively, you can just alter the source manually until the next release comes.

UPDATE (11/18/2014):

A release has now been made that incorporates the fix from above so that you no longer have to pull source and build manually. You can view the release on Github or just get the latest build.

Solution 3

You shouldn't change how ui-route handles URL matching to accept case insensitive URLs (that will have unexpected problems), but you can attempt to correct URLs for the user automatically when the routes fail.

When ui-route can not match a URL to a route it triggers the otherWise() callback. I'll show you have to redirect using this callback.

The following makes the assumption that all URLs for your app should be in lower case.

var stateHandler = function($urlRouterProvider)
{
    $urlRouterProvider.otherwise(function($injector, $location)
    {
        var url = $location.absUrl();
        var redirect = url.toLowerCase();
        if(url == redirect)
        {
             return;
        }
        $window.location = redirect;
    });
};

YourAngularApp.config(['$urlRouterProvider',stateHandler]);

If you need more control, then use a regex to select which URLs need rewriting.

Share:
12,103

Related videos on Youtube

Darren Wainwright
Author by

Darren Wainwright

Updated on June 04, 2022

Comments

  • Darren Wainwright
    Darren Wainwright almost 2 years

    I'm building a new angularJS app, based from the AngularJS SPA Visual studio template (http://visualstudiogallery.msdn.microsoft.com/5af151b2-9ed2-4809-bfe8-27566bfe7d83)

    this uses ui-router (https://github.com/angular-ui/ui-router) for its routing.

    however, it seems to be case sensitive.

    Any idea how I would instruct angular/ui-router to ignore the case of the url parameter?

    case sensitivity doesn't matter while in the app, though should a user type a url to enter the application at a specific page, we need to ensure that about is also the same as aBouT

    Cheers

    • Sergiu Paraschiv
      Sergiu Paraschiv about 10 years
    • shaunhusain
      shaunhusain about 10 years
      Think you could post this as an answer Sergiu
    • Sergiu Paraschiv
      Sergiu Paraschiv about 10 years
      I think the answer here best describes the solution: stackoverflow.com/questions/14994324/… It's not a clear duplicate though.
    • Darren Wainwright
      Darren Wainwright about 10 years
      many thanks guys. new with angular so clearly missed these :)
  • Darren Wainwright
    Darren Wainwright over 9 years
    I'm not sure how this really differs from the method I ended up using (via the link in the question comments - $urlRouterProvider.rule() - other than the rule will apply any changes before attempting to find a route. Where as your solution is first checking all known routes, then changing the url and then redirecting.
  • Darren Wainwright
    Darren Wainwright over 9 years
    And by the way - you would want to use $window vs window to keep it all 'within' angualr.
  • Reactgular
    Reactgular over 9 years
    @Darren Yea I only saw the link in the comment after I posted. I'd go with rule()
  • Darren Wainwright
    Darren Wainwright over 9 years
    ah ok :) I supposed I should put an answer in here to help others :) - i'll do that now...
  • sebas2day
    sebas2day over 9 years
    I find this approach much better than the approved answer since it won't rewrite the url
  • Matt DeKrey
    Matt DeKrey about 9 years
    As of version 0.2.12 and later, this can be accomplished with a single line without rewriting the URLs. See @kmkemp's answer.
  • Axel
    Axel over 8 years
    Ageed with@MattDeKrey doing this will result in having $stateChangeSuccess trigger twice because of the rewriting of the url. Just put $urlMatcherFactory.caseInsensitive(true); in the run() function
  • Darren Wainwright
    Darren Wainwright over 8 years
    @Axel - StateChangeSuccess won't fire twice. It only fires once. Also mentions this in the comment in the code
  • Axel
    Axel over 8 years
    @Darren well, it happened to me just today, with the above code, using go(state) triggered twice stateChangeSuccess one with lowercase toParam and one with uppercase toParam....Commenting the line $location.replace().path(normalized); stopped this beviours...