Angular Routes not mapping properly for lazy loading - javascript

So I have an app with multiple modules that has routes properly put in place, and each module has it's own routes. Everything works fine, until I try to implement lazy loading.
Previous State:
example module
export const EXAMPLE_ROUTES: Routes = [
{ path: 'new', component: AddOpportunityComponent },
{ path: ':id', component: OpportunityProfileComponent,
children: [
{
path: 'edit/sdg-info', component: SdgInfoComponent
}
]}
];
I import this EXAMPLE_ROUTES in example module
Now I have root level routing as
const APP_ROUTES: Routes = [
{ path: '', component: HomeComponent},
{ path: 'search', component: SearchComponent },
{ path: 'example', component: ExampleComponent, children: [...EXAMPLE_ROUTES], canActivate: [AuthGuard, OnboardedGuard] },
];
export const appRouting = RouterModule.forRoot(APP_ROUTES, {enableTracing: true});
With this setup it works fine
After trying to have lazy loading
example module
const EXAMPLE_ROUTES: Routes = [
{ path: 'new', component: AddOpportunityComponent },
{ path: ':id', component: OpportunityProfileComponent,
children: [
{
path: 'edit/sdg-info', component: SdgInfoComponent
}
]}
];
export const exampleRouting = RouterModule.forChild(EXAMPLE_ROUTES);
and app routing becomes
const APP_ROUTES: Routes = [
{ path: '', component: HomeComponent},
{ path: 'search', component: SearchComponent },
{ path: 'example', loadChildren: './example/example.module#ExampleModule', canActivate: [AuthGuard, OnboardedGuard] }
];
export const appRouting = RouterModule.forRoot(APP_ROUTES, {enableTracing: true});
The problem I'm facing is, the example route works fine, now the /search route breaks, as the router for some reason tries to match it with opportunity route (path: ':id')
What might be going wrong here?

This issue can occoure when you first implement your FeatureModule in your RootModule and after a given time you decide you want to load this FeatureModule lazy via loadChildren and you forgot to remove FeatureModule from your imports in your RootModule.
In your case your Routing Configuration will look something like this after compilation (PSEUDO-CODE):
const Routes_CONFIG = [
{ path: '', component: HomeComponent},
{ path: 'search', component: SearchComponent },
{ path: 'example', loadChildren: './example/example.module#ExampleModule', canActivate: [AuthGuard, OnboardedGuard] }
{ path: 'new', component: AddOpportunityComponent },
{ path: ':id', component: OpportunityProfileComponent,
children: [
{ path: 'edit/sdg-info', component: SdgInfoComponent }
]
}
]
In your case, when you just enter /search you will match :id OpportunityProfileComponent. That's because the router accepts the first route that matches a navigation request path.

Related

Rerouting sub paths to a main path in angular

In my routes file I am trying to achieve the following.
const routes: Routes = [{ ...
{ path: '', component: MainComponent, children: [
{ path: 'routeA', component: ComponentA },
{ path: 'routeA/subA', component: ComponentAA},
{ path: 'routeA/subB', component: ComponentAB},
{ path: 'routeA/**', redirectTo: 'routeA'}
]}, ...}
The intention being that routeA/ will redirect back to routeA, but the above code doesnt achieve the intended effect.

How to group angular components with a root component like how the App-Component works

I have a few components that are all under account.
Username
Password
Profile
...
I want to have a parent component like how the app-component works, with a <router-outlet></router-outlet>, so that the main html of the parent component never changes but the contents of the <router-outlet></router-outlet>.
How do I go about this?
You can define your component route like
const appRoutes: Routes = [
{ path: '/main', component: appComponent },
{ path: 'login/:id', component: LoginComponent },
{
path: 'users',
component: userListComponent,
data: { title: 'User List' }
},
{ path: '',
redirectTo: '/users',
pathMatch: 'full'
},
{ path: '**', component: PageNotFoundComponent }
];
#NgModule({
imports: [
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
)
// other imports here
],
...
})
export class AppModule { }
then in your appComponent.html
<h1>your html</h1>
<router-outlet></router-outlet>
<h1>your html</h1>
https://angular.io/guide/router
You can use children or loadChildren(For Lazy Loading) concepts.
export const AppRoutes:Routes = [
{path: 'account', component: AccountComponent, children: [
{path: 'login', component: LoginComponent},
{path: 'profile', component: ProfileComponent}
]
In AccountComponent, you can add all common APIs and logic
In AccountComponentTemplate, add <router-outlet></router-outlet>
Use Angular Modularization concept for better maintenance.
Define your routes something like this:
const appRoutes: Routes = [
{ path:"", component: HomeComponent},
{ path:"accounts", component: AccountComponent, children:[
{ path:"user", component: UserComponent},
{ path:"password", component: PasswordComponent},
{ path:"profile", component: ProfileComponent}
]},
];
Define a <router-outlet> at root level as well as at child level. For child you can define it inside AccountComponent.html file.
You can follow something like this, that will help you in achieving what you require.
app.routing.ts
export const AppRoutes: Routes = [{
path: '',
component: PARENTcomponentName1,
children: [
{path: 'PATH1', loadChildren: 'MODULE_PATH'}
//more path
]},
{
path: '',
component: PARENTcomponentName2,
children: [
{path: 'PATH#', loadChildren: 'MODULE_PATH'},
]}}]

Angular2 CanActivate guard for all routes except one

I know that we can group routes located in one module. Like that:
canActivate: [AuthGuard],
children: [
{
path: '',
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
],
}
But I should add that guard to each module's routing file. And I have many of them.
I want that the user can not go to any route except one (login route) if he is not authorized.
What is the right way to add guard to all of them??
You can use a componentless empty path parent route with the guard
{ path: '', canActivate: [AuthGuard], children: [
{
path: '',
children: [
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
],
}
}
and in the guard check if the user is logged in.
If not logged in and the current route is login then still allow it.

How to make an optional root state in angular 2?

i need to do an optional prefix indicating on the language.
So you can go to
random-domain.com/
the default language will be selected(en)
and if you with selected language
random-domain.com/ru
language will be selected - ru
And this should apply to nested routes
random-domain.com/some-rand-entity and random-domain.com/ru/some-rand-entity
my non-working solution - an example
const app_common: Routes = [ ...];
export const app_routes: Routes = [
{
path: '',
component: HomeComponent,
resolve: {
settings: SettingsStore
},
pathMatch: 'full'
}
];
export const lang_routes: Routes = [
{
path: ':lang',
component: HomeComponent,
resolve: {
languages: LanguagesStore
},
children: app_common,
pathMatch: 'full'
}
];
export const routes: Routes = [
...app_routes,
...app_common,
...lang_routes,
...checkoutRoutes
];
You can use route parameters for this purpose
export const app_routes: Routes = [
{
path: '',
component: HomeComponent,
resolve: {
settings: SettingsStore
},
pathMatch: 'full',
children: app_common
},
{
path: ':lang',
component: HomeComponent,
resolve: {
settings: SettingsStore
},
children: app_common,
}
];
See also https://angular.io/docs/ts/latest/guide/router.html#!#route-parameters
This is something that should be handled with query parameters
url?lang=en
not with path parameters
url/en // don't do this
To add query params in routerLinks you would do
<a [routerLink]="..." [queryParams]="{ lang: 'en' }" >link</a>
To do with programmatically with Router, you would use
this.router.navigate(['...'], { queryParams: { lang: 'en' }});
To access the query params in a component, the ActivatedRoute has a queryParams property
this.route.queryParams.subscribe(params => {})
We can also preserve the query parameters so we don't need to keep applying them. In the routerLink we would do
<a [routerLink]="..." [queryParams]="{ lang: 'en' }" preserveQueryParams>link</a>
In the Router we would do
this.router.navigate(['...'], { preserveQueryParams: true});
What this does, is that when the current route has query params attached, when we navigate, the params will be automatically attached.
See Also:
Query Parameters and Fragments
Docs for RouterLink

Using children states in Angular 2 router throws error

Heres my router config:
import { RouterConfig } from '#angular/router';
...
export const AppRoutes : RouterConfig = [
{
path: '',
redirectTo: 'myview',
pathMatch: 'full'
},
{
path: 'myview',
component: ViewComponent,
children: [{
path: 'hello',
component: HelloComponent
}]
},
];
When I try to load the page I get the following error:
EXCEPTION: Error: Uncaught (in promise): Error: Cannot match any routes: ''
However, when I make the child route a sibling, like this:
export const AppRoutes : RouterConfig = [
{
path: '',
redirectTo: 'myview',
pathMatch: 'full'
},
{
path: 'myview',
component: ViewComponent
},
{
path: 'hello',
component: HelloComponent
}
];
I am able to load the page fine without any errors. What am I doing wrong?
Because the way you have designed it is on initial load it is landing on ViewComponent component but ViewComponent has child so have to redirect to inner component.
You need to add one more route to children routes which will redirect '' to hello component.
export const AppRoutes: RouterConfig = [
{ path: '', redirectTo: 'myview', pathMatch: 'full'},
{ path: 'myview', component: ViewComponent,
children: [
{ path: '', pathMatch: 'full', redirectTo: 'hello' }, //added redirection to hello
{ path: 'hello', component: HelloComponent }
]
}
];
Note: Make sure you have <router-outlet></router-outlet> in myview component HTML so that child route view can be shown
correctly.
You are not using any route for '' in your RouterConfig.
As after redirect the new path will be https://yourdomain/myview/. And for this you have only created https://yourdomain/myview/hello route in routeCofig
I have created an app in angular 2. You can check the source here on Github.
Just add following line to your children path array:
{path: '', component: HelloComponent }
Check hero.routes.ts and dragon.routes.ts files they will help you understand routing more clearly. Hope it will help. Thank you.

Categories

Resources