You seem to be missing the point of the basic setup here. @NgModule and @Component are separate things, and the building blocks of your application structure.
An @NgModule is an "organizational" block. Where it's purpose is to share resources between grouped things. So generally speaking this is what allows you to use declarations to allow other components to use others.
The other is the imports array, for which the only valid things must themselves be @NgModule. Anything from importsthat is similarly "exported" via it's own exports array property (such as other components).
That's the basic principles, and <router-outlet> is just another @Component, which happens to live in the exports property of RouterModule.
So however you have things organized, that RouterModule has to be a "localized export" of the present @NgModule scope encapsulating the current component. Sounds a mouthful, but it's actually pretty simple:
Most Basic Setup
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core'
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { NavComponent } from './nav.component';
@NgModule({
declarations: [
AppComponent, // nav is used from app
NavComponent, // router-outlet used in here
// Any additional local components
],
imports: [
BrowserModule,
AppRoutingModule // router-outlet imported
],
bootstrap: [AppComponent]
})
export class AppModule { }
app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
// any additional component imports
const routes: Routes = [
// route declarations and component mounts
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule] // router-outlet exported
})
export class AppRoutingModule { }
Feature Module Setup
Much the same but watch for the changes:
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core'
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { NavComponent } from './nav.component';
import { FeatureModule } from './feature.module'
@NgModule({
declarations: [
AppComponent, // nav is used from app
NavComponent, // router-outlet used in here
// Any additional local components
],
imports: [
BrowserModule,
AppRoutingModule, // router-outlet imported
FeatureModule // <-- Import only for "static" load and not "lazy"
],
bootstrap: [AppComponent]
})
export class AppModule { }
app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
// any additional component imports
const routes: Routes = [
// route declarations and component mounts
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule] // router-outlet exported
})
export class AppRoutingModule { }
feature.module.ts
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FeatureComponent } from './feature.component';
import { FeatureRoutingModule } from './feature-routing.module';
@NgModule({
declarations: [
FeatureComponent,
// any components in the feature
],
imports: [
CommonModule,
FeatureRoutingModule // <-- each feature "should" control it's own routes
]
})
export class FeatureModule { }
feature-routing.module
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { FeatureComponent } from './feature.component';
const routes: Routes = [
{
path: 'feature',
component: FeatureComponent
}
];
@NgModule({
imports: [RouterModule.forChild(routes)], // .forChild() injects to existing provider
exports: [RouterModule] // <-- allows "local" componets to use routerLink etc
})
export class FeatureRoutingModule { }
Those basically represent your use cases, with everything else being a slight variation off of that. But is you generally follow the structure then you cannot go wrong.