Activate router-link that has multi level nested routes with CRUD setup - javascript

I trying to setup deep nesting like below, and I am kinda sure about we cannot use exact in router-link for nested routes.
<div id="app">
<nav class="nav nav-main">
<router-link exact to="/" class="nav-link" activeClass="active">Dashboard</router-link>
<router-link to="/projects" class="nav-link" activeClass="active">Projects</router-link>
</nav>
<div class="parent-content">
<h4>Content for Parent goes here</h4>
</div>
<router-view>
<nav class="nav nav-main">
<router-link :to="'/projects/' + $route.params.projectId" class="nav-link" activeClass="active">Deals</router-link>
<router-link :to="'/projects/' + $route.params.projectId + '/commitments/'" class="nav-link" activeClass="active">Commitments</router-link>
</nav>
<router-view>
<div class="child-content">
<h4>Content for Child goes here</h4>
</div>
</router-view>
</router-view>
</div>
My Route:
routes: [
{
path: '/',
component: Dashboard
},
{
path: '/projects',
component: Projects
},
{
path: '/projects/:id',
name: 'projects-detail',
component: ProjectDetails,
children: [
// DEALS
{
path: '/projects/:projectId/deals',
component: Deals
},
{
path: '/projects/:projectId/deals/:dealId/details',
component: DealDetails
},
// COMMITMENTS
{
path: '/projects/:projectId/deals/:dealId/commitments/:commitmentId/edit',
component: CommitmentEdit
}
]
}
]
With the above setup, I need to activate router-links, when the route is:
/projects/:projectId/deals/:dealId/details then activate Deals
/projects/:projectId/deals/:dealId/commitments/:commitmentId/edit then activate Commitments

I think you have not another <router-view></router-view> inside ProjectDetails component add this and try.
Also remove /projects/:projectId from all child path as you have already in parent path path: '/projects/:id',
So final you route would be
routes: [
{
path: '/',
component: Dashboard
},
{
path: '/projects',
component: Projects
},
{
path: '/projects/:id',
component: ProjectDetails,
children : [
// DEALS
{
path: 'deals/:dealId/details',//path will be /projects/:projectId/deals/:dealId/details
component: DealDetails
},
{
path: 'deals',.// path will be /projects/:projectId/deals
component: Deals
},
// COMMITMENTS
{
path: '/deals/:dealId/commitments/:commitmentId/edit/',
component: CommitmentEdit
}
]
}
]
Here is working fiddle : https://jsfiddle.net/chyLjpv0/16/
Read more about child path.
If you need not and component depended on parent dont make it as child use directly as root path like
routes: [
{
path: '/',
component: Dashboard
},
{
path: '/projects',
component: Projects
},
{
path: '/projects/:id',
component: ProjectDetails,
},
// DEALS
{
path: '/projects/:projectId/deals/:dealId/details',
component: DealDetails
},
{
path: '/projects/:projectId/deals',
component: Deals
},
// COMMITMENTS
{
path: '/projects/:projectId/deals/:dealId/commitments/:commitmentId/edit/',
component: CommitmentEdit
}
]
Working fiddle for this : https://jsfiddle.net/chyLjpv0/17/
Class router-link-exact-active is already working in this example : https://jsfiddle.net/chyLjpv0/18/ to display link as active
In your edit
Why you put <router-view> inside <router-view>. Outer is only working as it is being replaced and inner <router-view> is worthless. Use <router-view> in parent component for child component.
Also your inner <router-view> is not closed properly like </router-view>

Related

Angular Navigate Routing between parent and child

I have 2 components with parent and child relations. In the parent component, I have images which on click should navigate to child component. Following is my code, the URL in the browser is changing but the page isn't navigating.
Routing
const routes: Routes = [
{
path: 'parent', component: ParentComponent, children: [
{ path: 'child', component: ChildComponent}
]
},
{ path: '**', component: LoginComponent }
];
HTML
<section>
<img src="imagePath" alt="" (click)="gotoProfile()">
</section>
<div>
<router-outlet></router-outlet>
</div>
TS
gotoProfile() {
this.route.navigate(['/parent/child']);
}
The navigation is working only when I use boolean variables to display hide on button click (which is not a good practise), as below. Using boolean values after navigating is throwing some problem, on click of back button in child component the parent component is not loading.
TS
gotoProfile() {
this.hideParentDiv = true;
this.route.navigate(['/parent/child']);
}
HTML
<section *ngIf="hideParentDiv ">
<img src="imagePath" alt="" (click)="gotoProfile()">
</section>
<div *ngIf="!hideParentDiv ">
<router-outlet></router-outlet>
</div>
Can anybody help me with this, any help is much appreciated.
Thank you.
The router-outlet is tag used to render the components. You should not hide it.It's like blocking a door before trying to get in. If you want to "hide" the elements, then you should move the router-outlet up in the navigation hierarchy. What this means is that you should make "Page of Images to Click" and "Page of Detail Image" siblings in the router. Like this:
const routes: Routes = [
{
path: 'home', component: ExampleComponent, children: [
{ path: 'images-page', component: ImagesComponent },
{ path: 'image-detail-page', component: ImageDetailComponent}
]
},
{ path: '**', component: LoginComponent }
];

Named router outlet doesn't render template in lazy loaded route

I have a problem with my angular 8 app, not rendering into a named router-outlet.
The routes are:
routes.module:
const routes: Routes = [
...
{
path: 'settings', loadChildren: './settings/settings.module#SettingsModule', canActivate
},
]
settings.module
RouterModule.forChild([
{
path: '', component: SettingsComponent
},
{
path: 'profile', component: ProfileComponent, outlet: 'settings_o'
},
{
path: 'users', component: UsersComponent, outlet: 'settings_o'
}
])
settings.component.html
<nav mat-tab-nav-bar color="primary" class="bg-whitesmoke primary">
<span mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="[{outlets: {settings_o: [link.link]}}]"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{link.label}}
</span>
</nav>
<router-outlet name="settings_o"></router-outlet>
When I click a link, the url in the address bar changes (e.g. to http://localhost:4200/settings/(settings_o:profile)), but no content is rendered to settings_o, nor do the components get loaded. There is no error in the console.
link.link is, for example simply profile like in settings.module's routes.
What do I need to change?
This is a known bug which has been discussed a lot: https://github.com/angular/angular/issues/10981
As far as I know it hasn't been solved completely but there are workarounds: https://github.com/angular/angular/issues/10981#issuecomment-454425220
You should give the lazy loaded module a default route and define the child routes for the components that you would like to open in the named outlet, for example:
RouterModule.forChild([
{
path: "default",
component: SettingsComponent,
children: [
{ path: "profile", component: ProfileComponent,outlet: "settings_o" },
{ path: "users", component: UsersComponent, outlet: "settings_o" }
]
}
]);
Of course you have to change the navigation to the SettingsComponent accordingly: routerLink='/settings/default'
I made a Stackblitz which is not an exact copy of your code but which shows how it can be solved: https://stackblitz.com/edit/angular-nctjpv
By the way, in your original solution, if you placed the named router outlet in the root component, I think it would display the child component but in the wrong place.

Display component data from nested routes - Angular

I have the following components:
TodosComponent (path: './todos/'): with html content <p>TODO WORKS</p>
AddTodosComponent (path: './todos/add'): with html content <p>ADD TODO WORKS</p>
DeleteTodosComponent (path: './todos/delete'): with html content <p>DELETE TODO WORKS</p>
Add and Delete are nested routes in Todos.
In my main AppComponent I have a sidenav with links for the 3 components (TodosComponent, AddTodosComponent, DeleteTodosComponent).
I am trying to display in the content area of AppComponent the contents of the 3 components whenever one is clicked from the sidenav.
When I click the child routes I am receiving this error: Cannot match any routes. URL Segment: 'todos/add'
How can I display in sidenav-content from AppComponent the html from the components when a link is clicked in the sidenav?
app-routing.module.ts
const appRoutes: Routes = [
{ path: '', redirectTo: '/todos', pathMatch: 'full' },
{ path: 'todos', component: TodosComponent, pathMatch: 'full', children: [
{ path: 'add', component: AddTodoComponent},
{ path: 'delete', component: DeleteTodoComponent},
]},
]
#NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
app.component.html
<mat-sidenav-container>
<mat-sidenav opened="true" mode="side" fixedInViewport="true">
<p>I am the sidenav</p>
<mat-nav-list>
<mat-list-item>
<a matLine routerLink="/todos">List Todos</a>
</mat-list-item>
<mat-list-item>
<a matLine routerLink="/todos/add">Add Todo</a>
</mat-list-item>
<mat-list-item>
<a matLine routerLink="/todos/delete">Delete Todo</a>
</mat-list-item>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
<p>Main Content</p>
</mat-sidenav-content>
</mat-sidenav-container>
What I want to achieve:
Excerpt from angular documentation
Technically, pathMatch = 'full' results in a route hit when the
remaining, unmatched segments of the URL match ''.
In your example, at the path todos, the remaining, unmatched part is /todos/add, which is not an exact match, and the router won't look the children inside that and skip to the next path (which you don't have any) and when none found, you get the error you are getting :)
Remove pathMatch: 'full' from /todos path and it should work:
const appRoutes: Routes = [
{ path: '', redirectTo: '/todos', pathMatch: 'full' },
{ path: 'todos', component: TodosComponent, children: [
{ path: 'add', component: AddTodoComponent},
{ path: 'delete', component: DeleteTodoComponent},
]},
]
Why we need children, as we are displaying all in the same router-outlet.
const appRoutes: Routes = [
{ path: '', redirectTo: '/todos', pathMatch: 'full' },
{ path: '/todos', component: TodosComponent },
{ path: '/todos/add', component: AddTodoComponent },
{ path: '/todos/delete', component: DeleteTodoComponent }
]

vue-router won't render template on nested route

So I have a route like this:
const routes = [{
path: '/',
component: Home,
children: [
{
path: "/health"
children: [
{
path: 'overview'
component: Overview
},
{
path: 'blood',
component: Blood
}
]
}
]
}]
and in the Home component I have something like this:
<template>
<div id="home">
<router-view></router-view>
</div>
</template>
But when I navigate to the /health/overview and /health/blood routes, the templates corresponding to the components won't render. I checked the apps $route objects, they correctly detect the routes and the components. Just the template won't render. I also have a <router-view> in my App.vue if that helps.
Is it not possible to have multi nested routes? Or am I missing something?
The health route should be like this:
{
path: 'health', // not '/health'
component: Health, // this can just be a dummy component with a <router-view/>
children: [...],
},
If you don't need the Health component at all for any reason (i.e. you don't have any shared functionality or template across each child), you can just remove the health route completely and replace it with this instead:
{
path: 'health/overview',
component: Overview,
},
{
path: 'health/blood',
component: Blood,
},

router-link not rendering links properly

I am trying to iterate over some data to produce my router-links
<router-link v-for="(data, dataKey) in dataObject"
:to="{ params: { dataKey: dataKey }}"
tag="li">
<a>
<span>
{{ dataKey }}
</span>
</a>
</router-link>
This creates the tags with the right strings but doesn't append dataKey to the link when I'm not one of the links I'm trying to build.
dataKey even prints out properly within the <span> </span>
However, when I navigate manually to one of the links, all the params are properly appended.
export const routes = [
{ path: '/', component: Home, beforeEnter: checkAuthentication },
{ path: '/dashboard',
component: Dashboard,
children: [
{
path: '',
component: DashboardHome,
name: 'Dashboard Home'
},
{
path: 'profile',
component: DashboardPhotos,
children: [
{
path: '',
component: DashboardPhotosHome,
name: 'Dashboard Profile Home'
},
{
path: ':dataKey',
component: PhotoViewer,
props: true
}
]
},

Categories

Resources