How to pass props to a page in Nuxt? - vue.js

All I'm trying to do is pass a parameter to a page in Nuxt. In Vue, it's easy:
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
or
<router-link to="/user/123">User</router-link>
You just need to define your route correctly in router.js.
I haven't found a way to do it in Nuxt.
There is some reference in the Nuxt documentation to using underscores to define dynamic routes here, which is just strange. How do you pass more than one prop? What if you don't want to mess up your page naming conventions?
But in any case, it simply does not work. It appears to be possible to get the value of the parameter only by accessing this.$route.params.myprop, which is bad practice as explained here.
So how do I set up route "/users/123", invoke the Users.vue component in /pages, and actually get "123" as a prop?
(No, I'm not going to use VueX. It's very poor practice to use global state simply to pass parameters.)

The underscore filename system is the recommended way to create dynamic routes on Nuxt.js.
How do you pass more than one prop?
The documentation has a section for dynamic nested routes:
pages/
--| _category/
-----| _subCategory/
--------| _id.vue
--------| index.vue
-----| _subCategory.vue
-----| index.vue
--| _category.vue
--| index.vue
This will give you a :category/:subCategory/:id route.
Also, you can use extendRoutes in nuxt.config.js, or the router-module if you want to avoid using the default Nuxt generated routes altogether.

Do you mean something like this?
<nuxt-link to="/user/:id">User</nuxt-link>
and now type in the url bar
http://yourDomain/user/123
And in the created lifecycle hook in the page user you should see the console log of 123
created(){
console.log("your id is: " + this.$route.params.id);
}

Related

Vue Router - Nested Routes Not Working as Expected

I'm trying to create a simple nested routing:
App (root component, main navigation)
Topic1 (sub-navigation)
Topic1/Sub
Topic2
My demo on Codesandbox has the following issues:
1. When navigating from /topic1 to /topic1/sub, I expected the content from topic1 to show up and the content from topic1/sub to be shown below, like this:
However, Topic 1 does not show anymore.
2. How can I avoid showing "App" twice?
I know I've added path: "/topic1", component: App, but only because without it the routing did not work at all. As per the comments in router/index.js:
component: App, // Option 1 - Navigation to topic1,2 and /sub works (why?) 'App' is displayed twice
component: Topic1, // Option 2 - Navigation to /sub does not work but at least 'App' is only displayed once
I seem to be missing something essential - thank you already for any answers.
App component is showing twice because it is mounted twice. First it is mounted in main.js when you create the app. Then it is mounted in router-view as the route component. To avoid this, you shouldn't use the App component in router, instead make another Layout component where you define the page layout to be used by the vue-router. Also, this will allow the scenario where, while having a single entry point for your app (App), you can define different layouts for different routes, if needed.
Regarding the first question, the content of Topic1 component is not shown when navigating to Sub route, because it is wrapped in router-view. router-view displays only the content of the current route component. Avoid placing any content in router-view as it will be replaced on route navigation. This will work:
<h1>Topic1</h1>
<h2>Topic1 Content</h2>
<p>
<router-link to="/topic1/Sub">/topic1/sub</router-link>
</p>
<router-view> </router-view>
Here is the working codesandbox.
Also I refactored a bit your router index.js.

update router link params from url

Let's say I have 3 route url as following.
<router-link to="/AAA">AAA</router-link>
<router-link to="/BBB">BBB</router-link>
<router-link to="/CCC">CCC</router-link>
From "AAA" I am selecting one id, let's say project id.
clicking on project from "AAA", I am redirecting to "BBB/Project/454" where 454 is project id.
Now I need to update router link "/BBB" & "/CCC" to be like "/BBB/Project/454" & "/CCC/Project/454". so that when user clicks on those links, project id persists.
How do I achieve this in vue router and router-link?
Vue router-link is reactive just like the rest of vue.
You can easily use a dynamic route by passing a variable in like <router-link :to="myBBBLink"> where myBBBLink is the variable holding your desired route path.
Also check out named routes (https://router.vuejs.org/guide/essentials/named-routes.html) which might be more appropriate for your use case.
Depending on where your router links reside you can either directly manipulate the :to targets or use a global state store (vuex) as EvilArthas has suggested.

Vuejs: data through the router-view

Is it a good practice to pass data through the router-view? I have a nested router and some children have to have access to the data that parent is having. I know Vuex is the way to pass the data all over the app, but I`d like to know what are the exact disadvantages of binding data to the router-view to make it available in the child components.
So for now I have something like that:
<router-view v-bind:list="array" />
You can programtically pass through router like below
from parent component trigger below fn on click or redirection
this.$router.push({
name: 'ChildRouteName',
params: {'type':'name', 'id': '1',}
})
and in child component receive the parameters like this
type = this.$route.params['type']
id = this.$route.params['id']
You can pass data to the rendered component using the router-view but most likely is not what you want.
Routing can happen from any part of your app, but if you pass info via router-view you need to update the data that is bound to the view, which in turn means to have access to the component enclosing the template that presents router-view. This ends up tightly coupling components or using the bus/vuex.
You could use Vuex to pass the information, but there is a much easier way to pass information when routing.
You can define your route to transform parameters set when routing to props to the component. More info here. This means that you can make a call similar to this:
<router-link :to="{ name: 'routeName', params: { id: 1 }}">Go to route</router-link>
and then whatever component is registered for routeName will get the prop id set to value 1. The same will happen if you trigger a navigation programatically.

path-to-regexp Find regular expression matching the route

I am adding dynamic child components while the page loads. Adding child routes in OnCreated of parent does not make the page work when we refresh the page.
Hence, I am parsing the page templates (as I know them when the page loads).
I am now looking for a way to know the route which matches the href. Vue-js uses path-to-regexp and my question is very simple.
I want to know the matching component
const router = new VueRouter({
routes: [
// dynamic segments start with a colon
{ path: '/user/:id', component: User },
{ path: '/foo/bar', component: FooBar },
]
})
// Reverse of this
var matchingComponent = howDoIDothis(/foo/bar) // this should give me the matching
I need this so that I can remove from the path and then add the child component to the parent dynamically.
You need to use Vue router's router.getMatchedComponents method. However, this method needs that your router is fully initialized with all the routes. Otherwise, there is no way. Vue-router doesn't expose underlying parsed Regular expressions against which you can compare your href.
Also, what you are trying to do is not the most idiomatic way of doing things in Single Page Applications. A good practice is to declare all your routes upfront in some JS file using which you should initialize your router. Of course, you will want to protect certain routes for which you should use Route guards.
Finally, when you have all your routes declared upfront means you have all the components bundled upfront in one big JS file. To avoid this, wrap your component in async wrappers and bundler like Webpack would be smart enough to split the bundle into multiple smaller files.

How to implement a sidebar that is bound to the route in nuxtjs

so I structured my pages folder like this
pages/
--index/
----page1/
------_slug.vue
----page2/
------_slug.vue
----page1.vue // contains different content
----page2.vue // contains different content
--index.vue
so the routes can be accessed like
/index
/index/page1
/index/page2
/index/page1/some-slug-here
/index/page2/some-slug-here
now, what I want to achieve is, when I access the route /index/page2/some-slug-here. it will show the sidebar component based on that route param.
so to show some visual, take a look at the attached image.
since nuxt don't seem to support named view routes. are there any other ways to achieve what I want?
thanks.
Nuxt.js does support named views. They are referenced as layouts in documentation and serve exactly that purpose.
It is possible to create multiple layouts in layouts folder and specify them for each page as following:
<template>
<!-- Your template -->
</template>
<script>
export default {
layout: 'sidebar'
// page component definitions
}
</script>