vuejs/router

Optional path segments

mrkamel opened this issue · 4 comments

What problem is this solving

We are looking for a way to specify optional path segments in a route, like e.g.

/companies/:companyNameSlug(/page/:page)?

meaning, the /page/:page part is optional. Either the whole segment is present when the page param is present or fully not present. However, this does not seem to be possible and all my research ended without a solution. path-to-regexp (not sure if vue-router is still using it) actually supports this via curly braces

/companies/:companyNameSlug{/page/:page}?

but it seems vue-router is escaping this before handing it over when i debug it using the path ranker tool https://paths.esm.dev/

I found some example https://github.com/vuejs/vue-router/blob/dev/examples/route-matching/app.js#L24 which looks like it should be possible but this is either outdated or not correctly supported by by the path ranker tool, as the braces also get escaped and it also does not work in my app.

Thanks in advance

Proposed solution

Optimally, the curly braces would be supported to implement optional path segments

/companies/:companyNameSlug{/page/:page}?

Describe alternatives you've considered

No response

@posva thanks a lot 👍 The neccessary escaping of the closing brace is very weird, though, IMHO

Additionally, this doesn't fully help with generating a url as the (?:page/([^/]+?\))? is only a constraint when parsing a path, but has no effect when generating one

const matcher = createRouterMatcher(
  [{ name: "someRoute", path: "/prefix/:slug/:page(?:page/(\\d+\\))?" }],
  {},
);

matcher.resolve(
  { name: "someRoute", params: { slug: "test-123", page: 4 } },
  { params: {} },
)

// => /prefix/test-123/4

reproduction https://codesandbox.io/p/devbox/qpktzz?file=%2Findex.mjs%3A11%2C1-15%2C1

Escaping always reads weird.
Yes, you will have to provide the whole param: page/54. In your specific case though, the / will be encoded since it's a param so you will need to build the fullpath yourself: router.push(/prefix/${slug}/page/${page}). There are plans to improve the handling of the / encoding in params in the future though