Angular, dynamic param on lazy loaded route not working - angular8

I have an Angular 8 App that has lazyloading working on all the pages, except for 2 that have dynamic parameters where something is not working correctly
From the app routing module
{
path: 'product',
loadChildren: './marketing/page/product/product-page.module#ProductPageModule'
},
From the ProductPageRoutingModule
const routes: Routes = [
{
path: '',
component: AppMarketingPageProductComponent,
children: [
{ path: ':slug', component: AppMarketingPageProductComponent },
{ path: ':slug', component: AppMarketingPageProductComponent },
{ path: ':slug/:secondary', component: AppMarketingPageProductComponent },
]
}
];
Routes are being put into the imports correctly, and the ProductRoutingModule is imported into ProductPageModule.
#NgModule({
imports: [
RouterModule.forChild(routes)
],
exports: [
RouterModule
]
})
export class ProductRoutingModule {}
In the AppMarketingPageProductComponent constructor
constructor( private route: ActivatedRoute ) {}
With these 2 I try to get the params within onNgInit function
this.route.params.subscribe( (params: Params) => {
console.log(params);
});
When I try to load the page I get an empty object. instead of "slug" or "slug" and "secondary" values key-value pairs.

The problem is that what I thought were child routes aren't really child routes so this
const routes: Routes = [
{
path: '',
component: AppMarketingPageProductComponent,
children: [
{ path: ':slug', component: AppMarketingPageProductComponent },
{ path: ':slug', component: AppMarketingPageProductComponent },
{ path: ':slug/:secondary', component: AppMarketingPageProductComponent },
]
}
];
needed to be changed to this
const routes: Routes = [
{ path: ':slug', component: AppMarketingPageProductComponent },
{ path: ':slug', component: AppMarketingPageProductComponent },
{ path: ':slug/:secondary', component: AppMarketingPageProductComponent },
];
now it works.

Related

Vue Router 4 - nested 404 (not found) routes redirect not working

these are my routes:
const routes: Array<RouteRecordRaw> = [
{
path: "/projects",
component: {},
children: [
{ path: "extensions", component: {} },
{ path: "themes", component: {} },
{ path: ":pathMatch(.*)*", redirect: "extensions" },
],
},
{
path: "/about",
component: {},
children: [
{ path: "experience", component: {} },
{ path: "documents", component: {} },
{ path: ":pathMatch(.*)*", redirect: "experience" },
],
},
{ path: "/:pathMatch(.*)*", redirect: "/projects/extensions" },
];
Expected result:
Navigating to /projects or /projects/asdasd -> redirects to /projects/extensions
Navigating to /about or /about/asdasd -> redirects to /about/experience
Navigating to /asdasdasd -> redirects to /projects/extensions
Current result:
Every incorrect path redirects me to /projects/extensions
I tried many combinations but nothing works as expected, please help.
Redirecting to child route
To redirect /projects to /projects/extensions, add a child route with a blank path that redirects to the target route:
const routes: Array<RouteRecordRaw> = [
{
path: "/projects",
component: () => import("../views/ProjectsView.vue"),
children: [
{
path: "",
redirect: "/projects/extensions", // or use a named route (see below)
},
⋮
],
},
}
Getting the redirect target right
When the redirect string is not an absolute path to a route (i.e., /about/experience), the path would be relative to the current route.
For instance, imagine being at /projects/themes and clicking /about/foo. This is how the final route would resolve:
/about/foo matches the wildcard route under /about, which redirects to /projects/themes/experience.
/projects/themes/experience matches the outer wildcard route, which redirects to /projects/extensions.
There are a couple ways to solve this...
Option 1: Use absolute path in redirect string
const routes: Array<RouteRecordRaw> = [
{
path: "/projects",
component: () => import("../views/ProjectsView.vue"),
children: [
{
path: "extensions",
component: () => import("../views/ProjectsExtensions.vue"),
},
{
path: "themes",
component: () => import("../views/ProjectsThemes.vue"),
}, 👇
{ path: ":pathMatch(.*)*", redirect: "/projects/extensions" },
],
},
{
path: "/about",
component: () => import("../views/AboutView.vue"),
children: [
{
path: "experience",
component: () => import("../views/AboutExperience.vue"),
},
{
path: "documents",
component: () => import("../views/AboutDocuments.vue"),
}, 👇
{ path: ":pathMatch(.*)*", redirect: "/about/experience" },
],
}, 👇
{ path: "/:pathMatch(.*)*", redirect: "/projects/extensions" },
]
demo 1
Option 2: Use named route in redirect object
const routes: Array<RouteRecordRaw> = [
{
path: "/projects",
component: () => import("../views/ProjectsView.vue"),
children: [
{
path: "extensions",
👇
name: "proj-ext",
component: () => import("../views/ProjectsExtensions.vue"),
},
{
path: "themes",
component: () => import("../views/ProjectsThemes.vue"),
}, 👇
{ path: ":pathMatch(.*)*", redirect: { name: "proj-ext" } },
],
},
{
path: "/about",
component: () => import("../views/AboutView.vue"),
children: [
{
path: "experience",
👇
name: "about-exp",
component: () => import("../views/AboutExperience.vue"),
},
{
path: "documents",
component: () => import("../views/AboutDocuments.vue"),
}, 👇
{ path: ":pathMatch(.*)*", redirect: { name: "about-exp" } },
],
}, 👇
{ path: "/:pathMatch(.*)*", redirect: { name: "proj-ext" } },
]
demo 2
Named routes are easier to maintain than paths, as (1) they avoid having to enter long paths, and (2) they could be moved without having to refactor paths.

Vue-router multiple active routes

Using vue-router, we have a nav menu which works, but we need an additional route to be recognized as "active" for the first nav item.
However the user starts their journey at "account/" (the root), which we show the same content for "/profile" as we don't intend on having actual homepage content to live in "account/".
Nav items:
account/profile ---> Needs class "router-link-active" for both "account/" and "account/profile" routes
account/plan
account/receipts
Routes:
const routes = [
{
path: '/account/',
component: ProfileBase,
children: [
{ path: '', name: 'AppHome', component: ProfileHome }
]
},
{
path: '/account/profile',
component: ProfileBase,
children: [
{ path: '', name: 'ProfileHome', component: ProfileHome },
]
},
{
path: '/account/plan',
component: PlanBase,
children: [
{ path: '', name: 'PlanHome', component: PlanHome },
{ path: 'cancel', name: 'PlanCancel', component: PlanCancel }
]
},
{
path: '/account/receipts',
component: ReceiptsBase,
children: [
{ path: '', name: 'ReceiptsList', component: ReceiptsList },
{ path: ':receiptID', name: 'ReceiptsDetail', component: ReceiptsDetail, props: true }
]
}
]

Angular distinguish route from paremetrized route

I have an Angular 8 app. In my router module I have something like this
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: ':code', component: CodeComponent },
{ path: 'not-found', component: NotFoundComponent},
{ path: '**', component: NotFoundComponent }
];
The problem here is that when I access (for an example) /not-found the component CodeComponent activates, but not the NotFoundComponent.
I want to distinguish /not-found page from parametrized /:code
Invert the order of your routes in your array so the 'not-found' definition comes before the ':code' definition. Like this
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'not-found', component: NotFoundComponent},
{ path: ':code', component: CodeComponent },
{ path: '**', component: NotFoundComponent }
];

Vue-router - using two different paths, children don't load from second path

children in route, name: matchDayRegistrationResult don't get loaded, when I move them to name: matchDays they load fine. But I need a different top level component, HomepageLayoutRatio5050 -> HomepageLayoutRatio2575
I could not find a working example in the Vue docs
const router = new VueRouter({
mode: 'history',
routes:
[
{
path: '/:lang',
name: 'matchDays',
component: HomepageLayoutRatio5050,
children: [
{
path: '/:lang',
components: {
descriptionBlock: MatchDaysDescription,
mainBlock: MatchDaysTable,
notesBlock: MatchDaysNotes
}
},{
path: '/:lang/matchday/registration/:id',
name: 'matchDayRegistration',
components: {
descriptionBlock: RegistrationFormDescription,
mainBlock: RegistrationForm
}
}]
},
{
path: '/:lang/matchday/registration/result/:id',
name: 'matchDayRegistrationResult',
component: HomepageLayoutRatio2575,
children: [
{
path: '/:lang/matchday/registration/result/:id',
components: {
descriptionBlock: RegistrationResultDescription,
mainBlock: RegistrationResultDetails,
notesBlock: RegistrationResultNotes
}
}]
}
]
});
HomepageLayoutRatio2575 does load,
but children: descriptionBlock: RegistrationResultDescription
mainBlock: RegistrationResultDetails notesBlock:
RegistrationResultNotes Don't.
Found THE solution, as the localisation part, /:lang was the culprit, blocking the second route (...logic) I reordered the routing schema.
To the benefit of people, having hard times, looking for complex vue router-view solutions, localisation aware, here's the solution :-)
const router = new VueRouter({
mode: 'history',
routes:
[
{
path: '/:lang',
component: HomeSweetHome,
children: [{
path: '/:lang',
name: 'matchDays',
components: {
homepageSidebarLayoutRatio: HomepageSidebarLayoutRatio5050,
homepageMainLayoutRatio: HomepageMainLayoutRatio5050,
footer: FooterGray
},
children: [
{
path: '/:lang',
components: {
descriptionBlock: MatchDaysDescription,
mainBlock: MatchDaysTable,
notesBlock: MatchDaysNotes
}
},{
path: '/:lang/matchday/registration/:id',
name: 'matchDayRegistration',
components: {
descriptionBlock: RegistrationFormDescription,
mainBlock: RegistrationForm
}
}
]
},{
path: '/:lang/matchday/registration/result/:id',
components: {
homepageSidebarLayoutRatio: HomepageSidebarLayoutRatio2575,
homepageMainLayoutRatio: HomepageMainLayoutRatio2575,
footerNotesBlock: RegistrationResultFooterNotes,
footer: FooterBlack,
},
children:[{
path: '/:lang/matchday/registration/result/:id',
name: 'matchDayRegistrationResult',
components: {
descriptionBlock: RegistrationResultDescription,
mainBlock: RegistrationResultDetails
}
}]
}]
}
]
});

Ionic 4 navigate to tabs

I'm working on an Ionic 4 project, I've generated a tabs project.
What I want to do is create a Login page which is the default page.
When a user has signed in successfully I want to navigate to the tabs.
When I'm trying to do this I get the error:
Error: Cannot match any routes. URL Segment: 'tabs'
These are my routes:
const routes: Routes = [
{ path: '', loadChildren: './login/login.module#LoginPageModule' },
{ path: 'Login', loadChildren: './login/login.module#LoginPageModule' },
{ path: 'tabs', loadChildren: './tabs/tabs.module#TabsPageModule' },
];
In my Login Page I have a button as follows:
<ion-button expand="block" [href]="'tabs'" color="light" fill="outline">Sign in</ion-button>
When I generate a different page I am able to navigate to this page using the same way.
I was facing the same issue. I found a solution here. You need to add an additional route to your routes array.
const routes: Routes = [
{ path: '', loadChildren: './login/login.module#LoginPageModule' },
{ path: 'Login', loadChildren: './login/login.module#LoginPageModule' },
{ path: 'tabs', loadChildren: './tabs/tabs.module#TabsPageModule' },
{ path: '', loadChildren: './tabs/tabs.module#TabsPageModule' },
];
Step 1 : Add an additional route to tabs page in your app-routing.module.ts
{ path: 'app', loadChildren: './pages/tabs/tabs.module#TabsPageModule' }
Step 2 : Add the tabs route inside the tabs-routing.module.ts
const routes: Routes =[
{
path:'tabs',
component:TabsPage,
children:[
{
path : 'home',
outlet : 'home',
component : HomePage
},
{
path : 'me',
outlet : 'me',
component : MePage
}
]
}
];
Step 3 : Link to the tabs page
<ion-button href="app/tabs/(home:home)" routerDirection='root'>Tabs</ion-button>
I faced the same issue. My first page is 'Sign In' page by default. I wanted to navigate to tabs module after button click.
app-routing.module.ts:
import { NgModule } from '#angular/core';
import { PreloadAllModules, RouterModule, Routes } from '#angular/router';
const routes: Routes = [
{ path: 'app', loadChildren: './tabs/tabs.module#TabsPageModule' },
{ path: '', loadChildren: './sign-in/sign-in.module#SignInPageModule' },
{ path: 'search', loadChildren: './search/search.module#SearchPageModule' }
];
#NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})
export class AppRoutingModule {}
tabs.router.module.ts:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { TabsPage } from './tabs.page';
const routes: Routes = [
{
path: 'tabs',
component: TabsPage,
children: [
{
path: 'home',
children: [
{
path: '',
loadChildren: '../home/home.module#HomePageModule'
}
]
},
{
path: 'my-requests',
children: [
{
path: '',
loadChildren: '../my-requests/my-requests.module#MyRequestPageModule'
}
]
},
{
path: 'add-request',
children: [
{
path: '',
loadChildren: '../add-request/add-request.module#AddRequestPageModule'
}
]
},
{
path: 'search',
children: [
{
path: '',
loadChildren: '../search/search.module#SearchPageModule'
}
]
},
{
path: 'profile',
children: [
{
path: '',
loadChildren: '../profile/profile.module#ProfilePageModule'
}
]
},
{
path: '',
redirectTo: '/tabs/home',
pathMatch: 'full'
}
]
},
{
path: '',
redirectTo: '/tabs/home',
pathMatch: 'full'
}
];
#NgModule({
imports: [
RouterModule.forChild(routes)
],
exports: [RouterModule]
})
export class TabsPageRoutingModule {}
sign-in.module.ts:
....
const routes: Routes = [
{
path: "",
component: SignInPage
}
];
#NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
RouterModule.forChild(routes)
],
declarations: [SignInPage]
})
....
sign-in.page.html:
<ion-button (click)="navigateToProfile()">Sign In</ion-button>
sign-in.page.ts:
navigateToProfile(){
this.navController.navigateRoot(`app/tabs/home`);
}
Overall, my solution was:
adding one more path: 'app' in my root module app-routing.module
navigating to root with route with NavController. See here for more details, I found it here.