Search code examples
javascriptvue.jsvue-routernuxt.jspath-to-regexp

How to add float validation to Vue Routers paths?


For some reason I can't get a float to work in vue router paths.

/category/:category(\d+)/:post([-+]?([0-9]*\.[0-9]+|[0-9]+))

I've got numbers to work with :category(\d+)
But for some reason a regex like this doesnt work :post([-+]?([0-9]*.[0-9]+|[0-9]+))

Whenever I test it with javascript it works. But it doesnt work when i put it in the path like above.

/[-+]?([0-9]*\.[0-9]+|[0-9]+)/.test(6.5) // MATCHES  /category/196/6.5
/[-+]?([0-9]*\.[0-9]+|[0-9]+)/.test(6) // MATCHES /category/196/6

Numbers I would like to match:

10
65.5
.55

If anyone has an idea how to resolve this please let me know!


Solution

  • Update:

    The version of path-to-regexp used by Vue Router is 1.7.0... ish. The exact way it pulls it in is complicated but I believe 1.7.0 gives the best match.

    With that in mind I came up with this:

    path: '/category/:category([0-9]+)/:post([-+]?[0-9]*\\.?[0-9]+)',
    

    It's a bit different to my original answer but it can also be tested using the testing site I mentioned if you change the version to 1.7.0.

    I have tested this with Vue Router and it seemed to work for me. I haven't tested it with Nuxt.

    The 'trick' here is that it doesn't make a special case for integers, they get matched automatically by making the dot optional. That gets rid of some of the special symbols from the path, leaving less scope for it to fall foul of the craziness of path-to-regexp.

    Original answer:

    I did a bit of experimenting using the Express Route Tester, which I believe is using the same path-to-regexp library as Vue-Router/Nuxt:

    https://forbeslindesay.github.io/express-route-tester/

    This seemed to work for me:

    /category/:category(\d+)/:post([-+]?(\d{0,}.\d+|\d+))
    

    Changes:

    1. Removed the extra forward slashes.
    2. Removed the backslash before the dot.
    3. Changed the * to {0,}, otherwise it gets converted to .* and things like 12xxx.34 will match.
    4. Changed the [0-9] to \d. Either is fine and if you're having to write it as a string it may be easier to use [0-9] to dodge the slash escaping. Whichever you pick, be consistent.