I am still getting used to Angular and how to properly structure different components and modules. I want to set my app up according to best practices and maximize efficiency. I currently have multiple modules. I have a "base" module that I want to navigate to, but depending on the URL, I want to incorporate components from other modules. Here is how my app-routing.module is currently set up:
const routes: Routes = [
{ path: '', component: BaseComponent },
{ path: 'featureone', loadChildren: () => import('./feature-one/feature-one.module').then(m => m.FeatureOneModule) },
{ path: 'featuretwo', loadChildren: () => import('./feature-two/feature-two.module').then(m => m.FeatureTwoModule) },
{ path: '**', redirectTo: '', pathMatch: 'full'}
];
I understand this routing is not set up properly, but I am not sure how I can properly set this up in the most efficient way.
Currently, if I navigate to ''
, it will load the BaseComponent as expected. If I add
<app-feature-one></app-feature-one>
or
<app-feature-two></app-feature-two>
to the BaseComponent template, it will throw an error like "Cannot access 'FeatureOneModule' before initialization"
Is there some way where I could keep routes such as 'featureone' and 'featuretwo' where it would navigate to the BaseComponent, and I could add logic to display <app-feature-one></app-feature-one>
or
<app-feature-two></app-feature-two>
and only load FeatureOneModule if I navigate to 'featureone' or FeatureTwoModule if I navigate to 'featuretwo'?
With your current configuration, because { path: '', component: BaseComponent },
is first, no matter what url you issue, it will always resolve to BaseComponent
. Angular resolves route by performing a DFS search and will stop at the first match, so you'd have to be concise when defining the routes.
A way to solve this would be do add pathMatch: 'full'
:
{ path: '', component: BaseComponent, pathMatch: 'full' },
...
it will throw an error like "Cannot access 'FeatureOneModule' before initialization"
You are getting this error because app-feature-one
and app-feature-two
are components that belong to lazy-loaded modules, so, unless you imperatively import those modules, you won't be able to use them.
Is there some way where I could keep routes such as 'featureone' and 'featuretwo' ...
A quick way to solve this would be to use named outlets:
const routes: Routes = [
{
path: '', component: BaseComponent, pathMatch: 'full',
children: [
{ path: 'featureone', loadChildren: () => import('./feature-one/feature-one.module').then(m => m.FeatureOneModule), outlet: 'feat-one' },
{ path: 'featuretwo', loadChildren: () => import('./feature-two/feature-two.module').then(m => m.FeatureTwoModule), outlet: 'feat2' },
]
},
{ path: '**', redirectTo: '', pathMatch: 'full'}
];
then, in your base-component.component.html
<router-outlet name="feat-one"></router-outlet>
<!-- ... -->
<router-outlet name="feat-two"></router-outlet>
In order to navigate to one of them(or to both at the same time), you'll have to use something like this:
[routerLink]="[{ outlets: { 'feat-one': 'featureone' } ... }]"