Create following file/directory structure:
/pages/test1/_param1.vue
/pages/test2/_param2/index.vue
Routes to be generated as:
/test1/:param1?
/test2/:param2
Routes are generated as:
/test1/:param1?
/test2/:param2?
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 anindex.vue
file in theusers/_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.
Have a look at:
https://github.com/nuxt/nuxt.js/blob/dev/test/unit/dynamic-routes.test.js
https://github.com/nuxt/nuxt.js/tree/dev/test/fixtures/dynamic-routes/pages
For how it is supposed to work (specifically the route test/users
)
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 anindex.vue
file in theusers/_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 anindex.vue
file in theusers/_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:
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]
@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?
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.