1

I have this route

.state('mystate', {
    url: '/{id}',
    templateUrl: '/views/partial.html'
});

The id param should be a guid in form like this "2a542f61-5fff-4607-845d-972e6c3ad1e4". How do i add this in the url "url: '/{id:?what should i put here}'".

Prasanna
  • 779
  • 5
  • 13
Reynaldi
  • 1,125
  • 2
  • 19
  • 41

3 Answers3

7

You can define your own type of parameter.

var GUID_REGEXP = /^[a-f\d]{8}-([a-f\d]{4}-){3}[a-f\d]{12}$/i;
$urlMatcherFactoryProvider.type('guid', {
  encode: angular.identity,
  decode: angular.identity,
  is: function(item) {
     return GUID_REGEXP.test(item);
  }
});

Here is a showcase on plunker with this solution

Then specify this type in url route expression:

.state('mystate', {
  url: '/{id?guid}',
  templateUrl: '/views/partial.html'
});

You can read more on that page in docs

just-boris
  • 9,468
  • 5
  • 48
  • 84
  • this is awesome. what is angular.identity? why do you put it in encode and decode? and in url, maybe you mean "{id:guid}" instead of "{id?guid}" – Reynaldi May 27 '15 at 23:19
  • the regex does not work. The regex from radim kohler below works for me. – Reynaldi May 27 '15 at 23:37
  • using $urlMatcherFactoryProvider.type failed if i have 2 states. '/{id?guid}' and '/create' – Reynaldi May 28 '15 at 01:54
  • `angular.identity` is an utility function which always returns first argument. It is used to transform parameter value into url segment. Once you work with strings there is no need to do any transforms – just-boris May 28 '15 at 10:20
  • @Reynaldi, I forked Radim's plunker and added type definition. It worked fine for me. Look at here: http://plnkr.co/edit/iEC71jK94OgmFJLc7Aa6?p=preview – just-boris May 28 '15 at 10:21
  • this is working if the GUID is at the end of the URL but not working if i have urls like /users/id:guid/edit (added by a child state in UI-Router) when its copied into a new browser window. it works fine when its navigated through ui-router but not when coming directly from server redirected to angular app. Any ideas why? – lahsrah Apr 07 '16 at 04:30
  • To add more info to my comment above, here is a plunker: http://plnkr.co/edit/kdKIG4ies3yuWS1z52f1?p=preview Try opening the links in new tab. Parent2.child links work but parent.child links don't. – lahsrah Apr 07 '16 at 05:05
  • Consider using a non-capturing group in the regex. – TrueWill May 02 '16 at 19:51
  • Is an `equals` function required? – TrueWill May 02 '16 at 20:00
  • Have you tested this type with `$urlRouterProvider.otherwise()` when the type is a substring of a URL and the regex doesn't match? I was seeing the `otherwise` not firing. A possible fix is to add `pattern`; see http://stackoverflow.com/questions/36991513/otherwise-for-states-with-typed-parameters – TrueWill May 03 '16 at 16:54
6

There is a working plunker

We can just provide regexp in the url definition:

url: "/{id:(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12})}",

Read more about our options for url defintion:

http://angular-ui.github.io/ui-router/site/#/api/ui.router.util.type:UrlMatcher

small snippet:

'{' name ':' regexp|type '}' - curly placeholder with regexp or type name. Should the regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash.

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • any idea to make it more compact? url: "{id:(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12})}{id2:(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12})}/{id3:(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12})}" does not look readable – Reynaldi May 28 '15 at 01:51
  • If you are asking, I would be really open: do NOT use guid for url. Url should by user friendly as possible. That's just my position. But if you want to use it repetitively... we can use custom types, which do encapsulate that complexity. Check an example here: http://stackoverflow.com/a/30498590/1679310 – Radim Köhler May 28 '15 at 06:20
  • thanks for your comment. i know guid are ugly, but unfortunately, changing it is not an option right now. – Reynaldi Jun 10 '15 at 13:32
0

After much trial and error, I came up with:

$urlMatcherFactoryProvider.type('guid', {
    encode: angular.identity,
    decode: angular.identity,
    equals: function(a, b) { return a.toUpperCase() === b.toUpperCase(); },
    is: function(val) {
        // Local to avoid any lastIndex issues
        var GUID_REGEXP = /^[a-f\d]{8}-(?:[a-f\d]{4}-){3}[a-f\d]{12}$/i;
        return GUID_REGEXP.test(val);
    },
    // No anchors or flags with pattern
    pattern: /[a-fA-F\d]{8}-(?:[a-fA-F\d]{4}-){3}[a-fA-F\d]{12}/
});

This is based on @just-boris's answer. One key difference is pattern. Without this it appears that invalid GUIDs will not trigger $urlRouterProvider.otherwise().

TrueWill
  • 25,132
  • 10
  • 101
  • 150