Skip to content

UrlMatcherFactory defaults are not followed when building child states via UrlMatcher.concat #1477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
NevilleS opened this issue Oct 23, 2014 · 5 comments

Comments

@NevilleS
Copy link

Issue

When a new state is registered with the url attribute, a UrlMatcher is created for it, which is used to find the correct state whenever the location changes. The behaviour of UrlMatcher is controlled by the $urlMatcherFactoryProvider, which has two configurable defaults: strictMode and caseInsensitive. Whenever a new UrlMatcher is created via $urlMatcherFactory.compile, these defaults are applied. Therefore, if you set caseInsensitive to true, the URL matching will be case insensitive for all future matchers...

However, the behaviour of $state doesn't obey these defaults, since it almost never creates new UrlMatchers via compile, and instead uses UrlMatcher.concat, which (incorrectly?) ignores the default config specified by $urlMatcherFactory. Therefore, if you configure $urlMatcherFactory to use different defaults (e.g. caseInsensitive(true), strictMode(false)), it makes no difference: all your $state definitions end up using UrlMatchers that ignored the configured defaults.

Reproduction & Plunkr

There is a workaround: states with an absolute URL (one that starts with "^") use compile instead of concat, which brings in the default config correctly. Therefore, if you define three states like below, the 'home.concat' state doesn't match case-insensitively, whereas 'home.absolute' does!

$urlMatcherFactoryProvider.caseInsensitive(true)
$urlMatcherFactoryProvider.strictMode(false)
$urlRouterProvider.otherwise("/home");
$stateProvider.state({ name: 'home', url: '/home', controller: function() { }, templateUrl: 'home.html'});
$stateProvider.state({ name: 'home.concat', url: '/concat', controller: function() { }, templateUrl: 'concat.html'});
$stateProvider.state({ name: 'home.absolute', url: '^/home/absolute', controller: function() { }, templateUrl: 'absolute.html'});

You can try this out in this Plunkr: http://plnkr.co/edit/lDz2zIIchWqkSgHdyx9y?p=preview

Why?

I'd like to use the strictMode(false) behaviour to support trailing slashes in URLs, instead of specifying the other workaround of modifying the URL via a rule (which is in the FAQ). I need trailing slash support to keep both IE9 and modern browsers happy, and feel like this would be the cleanest approach.

Fix

I believe the best fix for this would be to remove UrlMatcher.concat and instead define $urlMatcherFactory.concat which does the same thing, except uses the default config instead. All existing uses of UrlMatcher.concat would be replaced with this.

I'm happy to put together a PR, if you guys think it makes sense. Thanks!

@christopherthielen
Copy link
Contributor

Love the detailed bug report! I think you're looking for this commit dd72e10 which is released in 0.2.12-pre1.

Please confirm, then close the issue if so.

@christopherthielen
Copy link
Contributor

related #1395

@NevilleS
Copy link
Author

Aha! Thanks Chris, I believe that's exactly what I need. I probably wouldn't have done the delegate object like in your PR, but works for me 👍

Probably should have done a better job searching previous issues... Ah well

@christopherthielen
Copy link
Contributor

Agreed, but backwards compatibility is a big factor.

@NevilleS
Copy link
Author

😢 isn't it always

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants