Nuxt.js: Unable to create a dynamic route with required parameter by following the guide

Created on 5 Jun 2019  路  21Comments  路  Source: nuxt/nuxt.js

Version

v2.8.1

Reproduction link

n/a

Steps to reproduce

Create following file/directory structure:

/pages/test1/_param1.vue
/pages/test2/_param2/index.vue

What is expected ?

Routes to be generated as:

/test1/:param1?
/test2/:param2

What is actually happening?

Routes are generated as:

/test1/:param1?
/test2/:param2?

Additional comments?

The guide says:

As you can see the route named users-id has the path :id? which makes it optional, if you want to make it required, create an index.vue file in the users/_id directory instead.

Following this advice (test2) results the parameter still being optional.

The test related to this functionality (https://github.com/nuxt/nuxt.js/blob/2fabea9402864828fe9aafe8b0d13bcc674a1b3b/packages/utils/test/route.test.js#L174-L184) seems to cover only cases where the parameter is defined in a filename, eg being the very last node.

I believe that any parameters specified as directories should be treated as required, so it would be possible to have full control over whether a route parameter is required or optional without resorting to any workarounds.

This bug report is available on Nuxt community (#c9312)
bug-report good first issue pending

Most helpful comment

Just came across this issue after tripping on documentation too... :)
If I may, +1 on changing code to behave as current doc says rather than changing doc to explain the double-file structure required for required params. I think that simply having a route with required param and relying on Vue Router's default behaviour (throwing 404 when no matching route is found) sounds much cleaner and intuitive.

Of course this kind of change would be potentially breaking so would require caution (maybe best suited for a major release?) - but that's definitely more in line with behaviour I'd expect.

All 21 comments

From what I can gather from this test is that one needs to create two routes, one for the intermediary path segment and other one for the parameter, like this:

/pages/test3/_param3.vue
/pages/test3/index.vue

But that would mean creating two routes. One that overrides the default case and rest will be handled by the parameter. Semantics wise this is ok as you'd normally expect the parent path tokens to always return something (however I don't exactly know if this is enforced by any sort of URI/HTTP specification).

If we ignore the semantics, creating two routes works around the problem, whereas a cleaner solution would be just one route that contains the required parameter part.

Is it really an intermediate path though? If you need _param3 to be required, vue-router still needs to know what to do when _param3 was not supplied. Therefore you need to create index.vue which forces you to implement a solution for when _param3 is empty.

So required means here required for rendering the page component A. If the param was not supplied then you shouldnt use page component A but page component B because component A expect that param to eg do a API request.

But why introduce the overhead of component B? I am quite sure that vue-router is capable of deciding that /test3 should not match the route /test3/:param3 and in that case just display a 404.

Thats true. To be honest I am not sure why it was created like the way it is

@pi0 @Atinux would you be ok with changing this behaviour or does it hold a deeper meaning?

Found the culprit, it's a documentation change :(

https://github.com/nuxt/docs/pull/888/files#diff-8017692b5218783a6438a7a1ed335c11

It looks like the two-file thing has been the intended pattern since the very beginning.

I personally would still like a change in behavior as it feels cleaner to me, but I fully respect if this is voted against.

@Ingramz what's the issue w/ the mentioned PR? :thinking:

@manniL sorry for being too vague. Essentially adding the word _instead_ to the end of the sentence completely changed the instructions.

As you can see the route named users-id has the path :id? which makes it optional, if you want to make it required, create an index.vue file in the users/_id directory.

First you had pages/users/_id.vue, now you need to also create pages/users/_id/index.vue, which turns :id required.

As you can see the route named users-id has the path :id? which makes it optional, if you want to make it required, create an index.vue file in the users/_id directory instead.

First you had pages/users/_id.vue, now you change it to pages/users/_id/index.vue, but it the parameter does not change to required.

Actually the first variant wouldn't work either because both files produce an equivalent result alone, the file needs to be pages/users/index.vue.

Thanks for your contribution to Nuxt.js!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you would like this issue to remain open:

  1. Verify that you can still reproduce the issue in the latest version of nuxt-edge
  2. Comment the steps to reproduce it

Issues that are labeled as pending will not be automatically marked as stale.

Got it. @Ingramz would you mind to create a PR to fix it? :relaxed:

I wouldn't mind, however I'll need to first understand whether my request of changing the behavior is reasonable compared to the way rest of the file to route mapping works.

If it turns out that is not a feasible option, I guess we can fix the documentation instead based on the knowledge gained from understanding the behavior better.

Just came across this issue after tripping on documentation too... :)
If I may, +1 on changing code to behave as current doc says rather than changing doc to explain the double-file structure required for required params. I think that simply having a route with required param and relying on Vue Router's default behaviour (throwing 404 when no matching route is found) sounds much cleaner and intuitive.

Of course this kind of change would be potentially breaking so would require caution (maybe best suited for a major release?) - but that's definitely more in line with behaviour I'd expect.

I close this issue because it not valid on the Latest version of Nuxt. The latest version is work as expected.
Below image shows directory structure and generated routes on [email protected]

Screen Shot 2020-07-23 at 2 59 26 PM

@farnabaz this has not been fixed. In your directory structure the param2 directory does not start with an underscore.

This is very unfortunate of me to miss the underscore. I will look for the reason of this cause.
Thank you @Ingramz for your notice 鉂わ笍

Should be fixed with v2.14.1

Confirmed. Thank you @farnabaz and @pi0!

Ok what if I have an optional parameter and a subroute of it.

pages/applications/_id/index.vue
pages/applications/_id/verification.vue

This was working as I expected before the release. _id is optional, and if the same path has a subroute (in this case verification), this time _id is required.

But after the related release, /applications does not work. And if I set the folder structure like this:

pages/applications/_id.vue
pages/applications/_id/verification.vue

It causes a ERR_TOO_MANY_REDIRECTS error.

The solution is just to change parameter for the one with the sub route. Like in this case; _id to _pid.

pages/applications/_id.vue
pages/applications/_pid/verification.vue

This solution feels like a workaround and I think this problem needs a fix to prevent future problems.

@melihplt probably it's best to file a new issue for the ERR_TOO_MANY_REDIRECTS case. That's exactly how one should solve that case.

Is changing the param name for nested routes really the suggested procedure here for making them required?

pages/applications/_id.vue
pages/applications/_pid/verification.vue

IMO this is really hacky and not ideal. What if Nuxt could just assume that any param is required if it's a directory and not a .vue file?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vadimsg picture vadimsg  路  3Comments

vadimsg picture vadimsg  路  3Comments

vadimsg picture vadimsg  路  3Comments

lazycrazy picture lazycrazy  路  3Comments

maicong picture maicong  路  3Comments