Vue Router - Nested Routes Not Working as Expected - vue.js

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.

Related

Change Nuxt Route Without Re-rendering

I have a Nuxt page and i want to change route path without re-rendering or refreshing page with a method on a button.
if i do this.$router.push() or replace(), page will refresh and if i do window.history.pushState() or replaceState() that works fine but after that if i add a query with this.$router.push({ query: a = b }) on my page, page will refresh because changing route with window.history will not change $route and when i use this.$router.push, Vue Router thinks its a different page.
I've done a lot of search on internet and did not find anything, so please don't label this question as duplicate.
What you're actually looking for is a Default Layout and some nested routes. Here is an example on how to achieve this in Nuxt with just a few steps: https://nuxtjs.org/examples/routing-nested-pages
Finally i solved this problem with using parent page and nuxt childs, i changed tabs to nav and rendered base components on parent page and other things on child pages and now it works fine. Tnx to #kissu and #Braks.

Vue-Router add new route dynamically when there is a new component

I need to create a fully modular Vue project and I can't figure out how do I add or remove routes when there is a new component or a component is deleted.
Now I statically type all the routes that are available in my Sidebar menu. Let's say there are 10 menus in my sidebar, it means that I should type 10 routes in my routes.js file.
But I need this project to be modular. By saying modular what I mean is, I need to give the component list to the project, I think that I should do that with a .json file and let's say this file says that it has only 5 component available, then the related routes will be dynamically created in the routes.js file, and when one of them is deleted, the related route should be removed from the routes list as well. That is what I want.
I want to do that because I develop a single frontend with Vue for more than one device. These devices may have different options and menus, when the device and the frontend matches, only the available menus will be put in the sidebar, so I can't type all the routes statically as I've been doing the whole time.
Any advice would be appreciated.
You can loop through a list of routes and use the router.addRoute function to dynamically add them to your router instance (requires vue-router 3.5.0+), instead of loading them by default. You could do this from the created() hook of your main layout for example.
// app.vue
<template>
<router-view />
</template>
<script>
export default {
created() {
let routes = loadRoutes(); // insert your own function to get the correct routes here
routes.forEach(route => this.$router.addRoute(route))
},
};
</script>
If you need to be able to switch between different layouts on the same device (like a shared terminal for managers and employees) you can reset the routes array by creating a new router instance, or removeRoute (if you use v4.0+).

How use two v-navigation-drawer?

I would like to use two v-navigation-drawer in my application.
I want to put the second v-navigation-drawer on v-content of the v-app.
This image, I put the sample image inside v-content.
Because, I created the routes. And when clicked in item of the second v-navigation-drawer, will open the other component next to v-navigation-drawer.
Ex:
blabla/settings/profile
blabla/settings/conf
Link: https://vuetifyjs.com/en/components/application/
So the routes are kind of nested according to your examples: a Settings in 1st Drawer and Profile & Conf in 2nd/child drawer. Let's call those Nested Routes.
1) If you wish to have those drawers as you wished, you need to create:
1 MainDrawer.vue component that wraps 1 ChildDrawer.vue child component which contains/wraps the <router-view> (if you're using vue-router). You will have to connect the links by append <router-link to="/settings/profile"> and other routes under Settings. You will have to toggle the drawer "open" state of 2nd child drawer if reached /profile or /config routes.
2) Instead of that approach, Vuetify has Nested List(link here) that solves your child routes with v-list-group component up to 2 levels in-depth (which is sufficient for your case as well).

Switching Between Components in a Vue App

I'm building a single-file-based Vue application from a template generated with the Vue UI tool.
I understand how a .vue file defines the styling/structure/behavior of a component, how smaller components can be composed into bigger components, and how the top-level "App" component mounts everything to an HTML Div.
As the user progresses through the app, though -- say from a login screen to a master screen to a detail screen -- what's the accepted approach to switching out the current screen-level component?
Ty in advance.
--The Vuebie
This is quite an open ended question so ill just show you what I have done in my own projects. I split my components directory into two directories; 'pages' and 'common'. (Ignore the 'firebase' directory is it beyond the scope of this question).
The common directory holds components that may be used in a page or re used in several different pages.
For example the 'account form' is used in my 'Edit Account page' and the category bar is used in several of my pages.
The pages directory holds components that are technically no different from my common components but they represent full pages on my website. A page component may contain several common components.
Now the biggest distinction between common and pages is in the router. I route different paths relative to the main url (that is probably not the technically correct description but hopefully you get the point) to each of the pages. Here is my index.js file from my router directory:
As you can see, I have a route pointing to each one of my pages. You can " switch out the current screen-level component" (as you put it) by using router-link tag's to navigate between different page components. These are clickable urls that your client can use, they can also be wrapped in buttons and such.
For example, this router link navigates to my home page, the component name is 'Helloworld'. See its corresponding reference in my router's index.js and in the pages directory so you can connect it all in your head.
<router-link class="nav-item nav-word" :to="{ name: 'HelloWorld' }">
Finally, I will talk a bit about the App.vue file. The App.vue acts like a base component as it contains the 'router view' tag within it's template:
<router-view/>
This means that every page that you route will be placed in the position of the 'router view tag'. I.e this tag will be replaced with the page. It is common practise to surround this tag with html code that you would like to be shown in each page. For example I have my router view tag between my nav bar and footer. So that the nav bar and footer will show on each page.

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>