Vue router fails to load child route - javascript

I am trying to set up router in my Vue app. Everything seemed to work fine until i started to try implementing children routes. Now when i try to access child route i get an error message along with some warnings:
What happens when i click on child router-link
My router setup:
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', redirect: '/welcome' },
{
name: 'welcome',
path: '/welcome',
component: WelcomePage
},
{
name:'noteLists',
path: '/noteLists',
component: NoteListLinks,
children: [
{
name:'noteListSheets',
path: ':id',
components: FullNoteSheet
}
]
}
],
linkActiveClass: 'active'
});
All other route links work fine.
The components template where child links are used and rendered looks like that:
<template>
<router-link
:to="setNoteListLink(entry.id)"
:key=entry.id
v-for="entry in notesListEntry"
>
{{entry.name}}
</router-link>
<router-view></router-view>
Function setNoteListLink just creates a links like '/noteList/1'.
The error says that it "Cannot read property 'writeDebug' of undefined" and writeDebug is a method on a component that it tries to load when i click on the route (FullNoteSheet), so i assume there is something wrong with the component and not the router. But component works just fine if i try to load it separately, by jst putting it in App component template.
If you have dealt with such issues and know the solution please let me know.

You have a typo in the noteListSheets route; It should be component: FullNoteSheet not components: FullNoteSheet

Related

Angular named router outlet no matched routes

I am working on an application that uses lazy-loaded modules for each main part of the app. I have one that I two router outlets in a primary one and one called details.
const routes: Routes = [
{ path: '', component: BooksComponent, resolve: {books: BooksResolver},
{ path: ':id', component: BookDetailsComponent, resolve: { book: BookResolver},outlet: "details"},
];
with the HTML like below
<router-outlet></router-outlet>
<router-outlet namme="details"></router-outlet>
Then each book item I have a router link like below
[routerLink]="['/', { outlets: { details: [book.id] } }]"
When I click on an item in I get the following error: ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: '53'. Currently I have the details displaying in the primary router outlet but I can not get the details to show when a user clicks on the book item. I am not sure why this is not working I looked in the documentation and This seems to be the correct way of doing it haveing all routes at the same level. ANy help would be appreciated.
I think you have a problem with multiple exits, so LET me give you a little example that I hope makes sense to you
{
path: 'a', component: AComponent, children: [
{path: 'd', component: DComponent},
{path: 'c', component: CComponent,outlet:'right'},
// a/(d//right:c)
]
},
In the component AComponent
<a [routerLink]="['./',{outlets:{primary:['d'],right:['c']}}]">d/c</a>
<router-outlet></router-outlet>
<router-outlet name="right"></router-outlet>
Multiple egress can be regarded as child routes

In Angular 8 Router parent route remains the same when navigating to the route with other parent

I'm working on a project written on Angular (v8.2.8) and use router with the same version. The architecture of the routing is the following:
I have app-routing.module.ts where I have 3 entries for routes array:
Shell.childRoutes([...array of routes]),
Case.childRoutes([...array of routes]),
{ path: '**', redirectTo: '/', pathMatch: 'full' }
Shell - that is parent component for app internal pages.
Case - that is parent component for app public pages.
Method child routes do almost the same for both components:
export class Shell {
static childRoutes(routes: Routes): Route {
return {
path: 'app',
component: ShellComponent,
children: routes,
canActivate: [AuthenticationGuard],
data: { reuse: true }
};
}
}
and
export class Case {
static childRoutes(routes: Routes): Route {
return {
path: '',
component: CaseComponent,
children: routes,
data: { reuse: true }
};
}
}
App have dashboard component for Shell parent and home component for Case parent.
User loads the page at home route and markup is the following:
<app-root>
<app-case>
<router-outlet></router-outlet>
<app-home></app-home>
</app-case>
</app-root>
And after redirect to the dashboard route I expect to have the following markup:
<app-root>
<app-shell>
<router-outlet></router-outlet>
<app-dashboard></app-dashboard>
</app-shell>
</app-root>
But I receive
<app-root>
<app-case>
<router-outlet></router-outlet>
<app-dashboard></app-dashboard>
</app-case>
</app-root>
So the exact issue is in test case:
User is on a route which exist in Shell parent.
Then if user will be redirected to any route in Case parent - the parent will stays the Shell. And the same situation works in other direction. If Case route was load first, after redirect to Shell route parent will stay the case.
I tried to edit different parameters in the childRoutes method, but no success, I just don't understand is it the issue in the engine, or I just need to specify some additional parameters.
Basically I resolved this issue. For those who had the same issue - for me issue was in custom route reusable strategy which was implemented. When I was switching from Case to Shell route-reusable-strategy function shouldReuseRoute returned true, so route was reused.

Redirect on startup by the given browser URL

I created a new Vue app with a base path. Due to the fact the app is embedded into another Vue app, this app doesn't render the router-view on startup. If you want to know more about how or why this app is embedded into another app, please have a look here:
mount Vue apps into container of main Vue app
and my own answer to this problem:
https://stackoverflow.com/a/58265830/9945420
When starting my application, it renders everything except the router-view. I want to redirect on startup by the given browser URL. This is my router config:
import Vue from 'vue';
import Router from 'vue-router';
import One from './views/One.vue';
import Two from './views/Two.vue';
Vue.use(Router);
const router = new Router({
base: '/my-embedded-app/',
mode: 'history',
routes: [
{
path: '/',
component: One,
},
{
path: '/two',
component: Two,
},
],
});
router.replace(router.currentRoute.fullPath);
export default router;
I want the app to render the component Two when calling .../my-embedded-app/two. Unfortunately, router.replace always redirects to / (so the browser URL is .../my-embedded-app/). I debugged the router, and saw that the path is /, but I would expect it to be /two.
Important note:
I don't want to redirect the user to /two whenever the url is /. I just want to render the view Two when the url is /two. Currently it doesn't.
What might be wrong? Maybe I don't even need that redirect, and can solve the problem a more elegant way.
updated: jsfiddle
What wound up happening is that route.currentRoute.fullPath was executed before router was ready.
That's the normal behavior, it is the way single page application works. The "pound" - like # - sign means that the links will not move the application to another page.
so you can change the router mode to
mode:"hash"
Try beforeEnter. Have a look at the below code:
const router = new Router({
base: "/my-embedded-app/",
mode: "history",
routes: [
{
path: "/",
component: One,
beforeEnter: (to, from, next) => {
// Your are free to add whatever logic here.
// On first visit
next("/two");
}
},
{
path: "/two",
component: Two
}
]
});
Read more about Navigation guards here
Could you provide a github repo or some to test the actual?
Otherwise my first idea is to use children routes with an "empty" view as base, here an example about what I tried. (working in my case)
router.js
export default new Router({
mode: 'history',
base: '/my-embedded-app/',
routes: [
{
path: '/',
name: 'base',
component: Base,
children: [
{
path: '',
name: 'one',
component: One
},
{
path: 'two',
name: 'two',
component: Two
}
]
}
]
})
Base.vue
<template>
<router-view/>
</template>
One.vue
<template>
<div>One</div>
</template>
Two.vue
<template>
<div>Two</div>
</template>

Multiple named router-outlet - component imported but not initialized and rendered

I'm using multiple named angular 8 router-outlet in a web app. All the routerLink seems to work as it changes the URL but components in my 2nd router-outlet are imported but not initialized nor rendered.
I made a Stackblitz available here : https://stackblitz.com/edit/ng-multiple-router-outlet?file=src/app/app.component.ts
As you can see, when you click on the sidebar, under photos you have a second navigation level by clicking on Google or Facebook but nothing is rendered.
In modules, components used in other modules and RouterModule are well exported to be accessible, I don't see what I've done wrong.
I tried to declare the routes with both forRoot and forChild methods, I put some logs, but I'm running out of clues.
Thanks for your help !
Angular router is pretty simple once you understand how nested routes works there.
Let's imagine a simple configuration:
RouterModule.forRoot([
{
path: '',
component: HomeComponent,
children: [
{ path: 'child', component: ChildComponent }
]
}
])
How would you use router-outlet to cover all routes above?
app.component.html
\
contains
\
<router-outlet></router-outlet>
\/
renders
\
HomeComponent
home.component.html
\
contains
\
<router-outlet></router-outlet>
renders
\
ChildComponent
The main takeaway here is that router-outlet renders component depending on router context. Once it renders component a new context is created and all router-outlet's declared at this level will look at children configuration.
The same is true for named routes.
You've generated the link like:
(selection:facebook//sidebar:photos)
It means that these named routes should be at the same root level. But you defined <router-outlet name="selection"></router-outlet> at nested level inside rendered by router LibraryComponent.
Let's add this outlet at the same level as 'sidebar':
<router-outlet name="sidebar"></router-outlet>
<router-outlet name="selection"></router-outlet>
and it actually works stackblitz
Now let's come back to your attempt. If you want to render selection components inside selection.component.html then you should be using nested named routed links:
selection.component.html
[routerLink]="['.', { outlets: { selection: [routeName] } }]"
\/
relative path
The above binding will generate nested links like (sidebar:photos/(selection:facebook))
Now you need to move SelectionRoutes configuration to children property of photos path:
selection.module.ts
imports: [
CommonModule,
RouterModule, //.forChild(SelectionRoutes)
],
sidebar.routes.ts
import { SelectionRoutes } from '../selection/selection.routes';
...
export const SidebarRoutes: Route[] = [
{ path: 'photos', component: LibraryComponent, outlet: 'sidebar', children: SelectionRoutes },
Stackblitz Example
Update
In order to make facebook as a default subroute you create a route with redirectTo option like:
export const SelectionRoutes: Route[] = [
{ path: 'facebook', component: FacebookComponent, outlet: 'selection' },
{ path: 'google', component: GoogleComponent, outlet: 'selection' },
{ path: '', redirectTo: '/(sidebar:photos/(selection:facebook))', pathMatch: 'full', },
]
Stackblitz Example

When are routed components initialized?

I have the following route:
path: ':id', component: ViewBookPageComponent },
And when added it produces the error:
Error: Cannot read property 'id' of null
I'm not performing a null check in the component since the property will be available when the component is navigated to and in this case the auth guard is also keeping rerouting to login prior to any of the book routes being shown.
This is a stacblitz demo:
https://stackblitz.com/edit/angular-ngrx-slice-demo-fork-with-id-route?file=src%2Fapp%2Fbooks%2Findex.ts
If I comment out the route, the error no longer appears, so it seems Angular is instantiating the component prior to it being routed to.
Is the following fix your problem?
const routes: Routes = [
{
path: 'find',
component: FindBookPageComponent,
},
children:[
{
path: 'result',
component: SearchResultComponent,
},
children:[
{
path: 'book/:id',
component: ViewBookPageComponent ,
}
]
]
]
The AuthGuard is not protecting the route. It needs to be declared within the Book module itself. See this question for more details.

Categories

Resources