Render nested routes as individual pages in VueJS - javascript

I'm using VueJS's own router component. In my admin interface, there is one page which shows an overview list and another one with specific options for one single entry.
function configRoutes() {
return [
{
path: '/',
redirect: '/default',
name: 'Home',
component: TheContainer,
children: [
{
path: 'admin/viewerRoles',
name: 'List',
component: AdminViewerRoles,
children: [
{
path: ':id-:name',
name: 'Settings',
component: AdminViewerRoleSettings
}
]
}
]
}
]
}
With that approach, I can place a <router-view /> tag in my AdminViewerRoles component. This will render the details page as viewport. What I wonder is, if it is possible to render either of the views without giving up the syntactically correct, nested navigation approach.
My idea would be to place the <router-view /> tag and the normal page content in two different div elements and render them conditionally with v-if. But is that really the best approach?
This would be my idea (untested):
<template>
<div v-if="$route.params.id">
<router-view />
</div>
<div v-else>
<table>...</table>
</div>
</template>

Related

VueJS navigate to child component

I have a button in a component that onclick will navigate to its child component.
Button code
<button class="summary" #click="navigateToSummary">
<span>Summary</span>
</button>
methods:{
navigateToSummary() {
return this.$router.push({
name: 'PortfolioSummary',
params: { coinId: this.coinSummary.coinId },
});
},
}
Router code
{
name: 'AppPortfolio',
path: '/portfolio',
component: AppPortfolio,
children: [
{
name: 'PortfolioSummary',
path: ':coinId',
component: PortfolioSummary,
props: true,
},
],
},
On clicking the button, the url updates in the browser, but it doesnt navigate to the child component.
What am I meant to change?
Your AppPortfolio view requires it's own <router-view> where PortfolioSummary will be rendered.
Basically when you use nested child routes in this manner they require a router-view inside a router-view to settle your 2 tree deep setup, a 3 for deep tree example will requires 3 nested router-views, so on and so fourth.
App.vue
<router-view>
AppPortfolio
<router-view>
PortfolioSummary

Vue router nested routes renders with parent

So Iv'e tried to nest my routes unsuccessfully using Vue router.
{
path: '/admin',
name: 'Admin', component: () => import('pages/Admin'),
children:[
{ path: 'stock', name: 'Stock', component: ()=> import('pages/Stock')},
]},
It did not work so I found out that I need to put inside the parent component.
Now it works but if I load the page /admin/stock it renders the two componets. one on top of the others.
Why the parent component (/admin page) is still displayed?
Btw when I did the same thing without nesting the routes it worked perfectly fine and the components rendered seperatly(the snippet below).
{
path: '/admin',
name: 'Admin', component: () => import('pages/Admin'),
children:[
//no nested route
]},
{ path: 'admin/stock', name: 'Stock', component: ()=> import('../pages/Stock')},
Thanks for the help
You should include in "Admin" component a router-view tag. Admin component will work as a "layout" and it will render the children corresponding to the current route.
In example
Admin Component:
<template>
<div>
<div>
Content present in all childrens
</div>
<router-view>
<div>"Admin" page content</div>
</router-view>
</div>
</template>
Stock component:
<template>
<div>
"Stock" content
</div>
</template>
When you go to /admin
It will render:
<div>
<div>
Content present in all childrens
</div>
<div>"Admin" page content</div>
</div>
When you visit /admin/stock
It will render:
<div>
<div>
Content present in all childrens
</div>
<div>"Stock" content</div>
</div>
Here you have a better example
https://router.vuejs.org/guide/essentials/nested-routes.html
If you don't need reuse "Admin" component layout, you could use routes as you mentioned in the second case, without nesting them

Nuxt - How to Render Child Route without Parent Content

I am wondering how to display the content of a child page without showing the parent.
I figured this would be straightforward, but I've found nothing about how to do this. My current output has page 'app/parent' rendering some content for the parent, and 'app/parent/child-A' displays that same content from the parent with the child's content at the bottom. I'd like to only display the child's content while maintaining the 'app/parent/child-A' URL.
I suspect that I may be approaching the parent/child functionality in nuxt wrong and there is some better option for what I'm trying to do.
you can use v-if
router.js
....
const page = path => () => import(`./pages/${path}.vue`).then(m => m.default || m);
const routers = [
{
path: '/posts',
component: page('posts/layout'),
props: true,
children: [
{
path: '',
name: 'posts/index',
component: page('posts/index'),
props: true
},
{
path: ':id',
name: 'posts/show',
component: page('posts/show'),
props: true
}
]
},
...
];
...
pages/posts/layout.vue
<template>
<main>
<h1 v-if="$router.name !== 'posts/index'">from parent layout</h1>
<nuxt/>
</main>
</template>

Ionic 4 and using material tabs router outlet

I am wanting to use Material Tab's (https://material.angular.io/components/tabs/api#MatTabLink) within my Ionic 4 project, now, the requirements are that I need to house multiple views in a tab and the first thought was that I can use a new ion-router-outlet or router-outlet within my parent component.
Bare in mind that I do already have one router outlet for the main app.
I am lazy loading the main chat routes in my app-routing.module.ts, this page is responsible for loading the tabs.
{ path: 'chat', loadChildren: './chat/chat.module#ChatPageModule', canActivate: [ AuthGuard ]}
Now, in my chat.module.ts I have the following routes:
{ path: '', component: ChatPage },
{ path: 'active', component: ActivePage },
{ path: 'messages', component: MessagesPage },
{ path: 'teams', component: TeamsPage }
ChatPage component is my parent tab view page. The others I am wanting to be in a tab.
The HTML for displaying these tabs is in chat.page.html and looks like this:
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of routeLinks"
[routerLink]="link.path"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{ link.label }}
</a>
</nav>
<router-outlet></router-outlet>
I have also tried <ion-router-outlet></ion-router-outlet> but this throws up more issues.
The main issue here is that the routes look as though they are loading up in the main router outlet rather than the child one, I have tried adding the name attribute to the mark up but my IDE states that it's not valid and doesn't seem to work.
Ok, I have figured it out, and I am going to look stupid for not trying this before but the issue was that in order to use this child router-outlet the routes I wanted in tabs need to child routes.
{ path: '', component: ChatPage, children: [
{ path: 'active', component: ActivePage },
{ path: 'messages', component: MessagesPage },
{ path: 'teams', component: TeamsPage }
] },

Deeply nested Angular routes

A the root of my app I have a "demo" route to a module that handles all the demos on the site:
{
path: 'demo',
canActivate: [AuthGuardService],
loadChildren: './demo/demo.module#DemoModule'
}
Then, in the demo module's routing module I have all the demos, some of which are also modules, such as
{
path: 'splitviews',
loadChildren: './splitviews/splitviews.module#SplitviewsModule'
}
Which is a module of demos of types of "Splitviews", components with 2 named route outlets: 1 for the left nav and 1 for the content:
<app-header class="site-header"></app-header>
<div class="site-content"></div>
<div [ngClass]="containerType"
class="splitview-wrapper">
<div class="row">
<div class="col-sm-2"">
<router-outlet name="leftnav"></router-outlet>
</div>
<div class="col-sm-10">
<router-outlet name="content"></router-outlet>
</div>
</div>
</div>
<app-footer class="site-footer"></app-footer>
So far, this module has routing like this
path: 'basic',
component: SplitviewsComponent,
data: {
containerType: 'container'
},
children: [
{
path: '',
component: LeftnavBasicComponent,
outlet: 'leftnav'
},
{
path: '',
component: Content1Component,
outlet: 'content'
}
]
},
So now if you went to /demo/splitviews/basic you'd see the splitviews component with the header, footer, and the 2 route outlets displaying LeftnavBasicComponent and Content1Component.
But now what I need to do is have the links in the LeftnavBasicComponent load different content components (e.g. Content2Component) inside the router-outlet "content". And I'm not sure how to best configure those sub-routes.
You can use the LeftnavBasicComponent and Content1Component as placeholders and then the components you really want to show will be loaded inside them depending on a value you'll pass by url.
Your html will be like below
<app-header class="site-header"></app-header>
<div class="site-content"></div>
<div [ngClass]="containerType"
class="splitview-wrapper">
<div class="row">
<div class="col-sm-2"">
<app-leftnav></app-leftnav>
</div>
<div class="col-sm-10">
<app-content></app-content>
</div>
</div>
</div>
app-leftnav and app-content are respectively the selectors of LeftnavBasicComponent and Content1Component.
The routing module will simply look like below:
{
path: 'basic/:leftnavtype/:contenttype',
component: SplitviewsComponent,
data: {
containerType: 'container'
}
}
Now in the LeftnavBasicComponent typescript file we have to take the value of leftnavtype from the url and put it in a variable like below:
leftNavType: string;
ngOnInit() {
this.route.params.subscribe((params: Params) => {
this.leftNavType = params["leftnavtype"];
});
}
And finally in the LeftnavBasicComponent html file we show a specific component depending on the leftNavType value
<app-type-1-left-nav *ngIf="leftNavType==='type1'"></app-type-1-left-nav>
<app-type-2-left-nav *ngIf="leftNavType==='type2'"></app-type-2-left-nav>
The same will be done for the content placeholder.
After doing so, if you call /demo/splitviews/basic/type1/content3, the type1 component will be loaded in the left nav placeholder and the content3 component will be loaded in the content placeholder, and you can then generate the link you want in the navigation part to load a specific component in the content part.
It may not be the perfect solution, but it works in your case.
And if there is only few cases, I suggest simply creating a route for each one, both solutions work depending on your needs.
Happy to clarify more if needed!

Categories