What Is the Router Outlet in Angular and How Does the router-outlet Tag Work?
The <router-outlet> tag in Angular acts as a placeholder directive that dynamically renders the component matching the current URL, serving as the bridge between the Angular router and the DOM.
The router outlet in Angular is the fundamental mechanism that transforms URL navigation into visible UI components. Located in the angular/angular repository, the RouterOutlet directive implementation in packages/router/src/directives/router_outlet.ts provides the core logic for component insertion and lifecycle management.
What Is the Router Outlet in Angular?
A router outlet is a structural directive that marks a specific location in your template where the Angular router can mount components based on the active route configuration. When you navigate to a URL, the router matches that path against the routes defined in RouterModule.forRoot() or RouterModule.forChild(), instantiates the corresponding component, and injects its view directly into the DOM at the <router-outlet> location.
Because the router operates on a tree structure of outlets, you can create named outlets using the name attribute (e.g., <router-outlet name="sidebar">) to render multiple routes simultaneously. This enables auxiliary routes for sidebars, dialogs, or modal content without disrupting the primary navigation flow.
How the router-outlet Tag Works Under the Hood
According to the angular/angular source code, the router outlet functionality spans several key files that handle directive implementation, state management, and lazy loading.
The RouterOutlet Directive Core Logic
The RouterOutlet directive is implemented in packages/router/src/directives/router_outlet.ts. This file contains the core class responsible for creating, destroying, and updating component views when route changes occur. The directive maintains a reference to the currently activated component and manages the attachment and detachment of views from the Angular change detection tree.
When a navigation event completes, the router communicates with the outlet to instantiate the new component using a ComponentFactoryResolver and project it into the view container at the <router-outlet> location.
Route State and Activation
The packages/router/src/router_state.ts file defines the ActivatedRoute and RouterState classes that track the current route configuration and URL parameters. The router outlet uses these state objects to determine which component to render and to provide the route context (parameters, query strings, data) to the instantiated component.
When a route with child routes is activated, the router creates a hierarchy of ActivatedRoute instances, allowing nested <router-outlet> elements to render child components while maintaining the parent context.
Practical Implementation of Router Outlet in Angular
Basic Router Outlet Usage
The most common implementation places a single <router-outlet> in your root component to handle primary navigation:
<!-- app.component.html -->
<nav>
<a routerLink="/home">Home</a>
<a routerLink="/about">About</a>
</nav>
<!-- The router renders matched components here -->
<router-outlet></router-outlet>
// app-routing.module.ts
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'about', component: AboutComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Named Router Outlets for Auxiliary Routes
You can create multiple outlets in the same template to render auxiliary content alongside your primary view. This is implemented in router_outlet.ts through the name property binding:
<!-- app.component.html -->
<a [routerLink]="[{ outlets: { sidebar: ['chat'] } }]">Open Chat</a>
<!-- Primary outlet -->
<router-outlet></router-outlet>
<!-- Named auxiliary outlet -->
<router-outlet name="sidebar"></router-outlet>
// app-routing.module.ts
const routes: Routes = [
{ path: 'dashboard', component: DashboardComponent },
{
path: 'chat',
component: ChatComponent,
outlet: 'sidebar' // Targets the named outlet
},
];
Handling Router Outlet Lifecycle Events
The packages/router/src/directives/router_outlet_events.ts file defines the event system that allows you to react when components are attached or detached. Bind to these events to implement caching, animations, or analytics tracking:
<!-- app.component.html -->
<router-outlet
(activate)="onActivate($event)"
(deactivate)="onDeactivate($event)"
(attach)="onAttach($event)"
(detach)="onDetach($event)">
</router-outlet>
// app.component.ts
export class AppComponent {
onActivate(component: any) {
console.log('Component activated:', component.constructor.name);
}
onDeactivate(component: any) {
console.log('Component destroyed:', component.constructor.name);
}
onAttach(component: any) {
// Called when a component is reattached from cache
}
onDetach(component: any) {
// Called when a component is detached but cached
}
}
Lazy-Loaded Modules with Router Outlets
The packages/router/src/config_loader/router_config_loader.ts handles the dynamic loading of feature modules. When a lazy-loaded module contains its own child routes, it uses its own <router-outlet> to render those children:
// feature-routing.module.ts (inside a lazy-loaded module)
const routes: Routes = [
{
path: '',
component: FeatureShellComponent,
children: [
{ path: 'list', component: ItemListComponent },
{ path: 'detail/:id', component: ItemDetailComponent },
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class FeatureRoutingModule {}
<!-- feature-shell.component.html -->
<h2>Feature Module</h2>
<nav>
<a routerLink="list">View List</a>
</nav>
<!-- Child routes render here -->
<router-outlet></router-outlet>
Summary
- The router outlet in Angular is a structural directive that creates a dynamic insertion point in the DOM where the router renders matched components.
- According to the
angular/angularsource code, the implementation inpackages/router/src/directives/router_outlet.tsmanages component lifecycle, whilepackages/router/src/router_state.tstracks the active route state. - Named outlets allow multiple simultaneous views using the
nameattribute, enabling auxiliary routes for sidebars and modals. - The outlet emits lifecycle events (
activate,deactivate,attach,detach) defined inpackages/router/src/directives/router_outlet_events.ts, allowing custom logic during component transitions. - Lazy-loaded modules work seamlessly with router outlets, as handled by
packages/router/src/config_loader/router_config_loader.ts, enabling feature-based code splitting with nested outlet hierarchies.
Frequently Asked Questions
What is the difference between router-outlet and RouterOutlet?
<router-outlet> is the HTML tag syntax used in Angular templates to mark the DOM insertion point, while RouterOutlet is the TypeScript directive class defined in packages/router/src/directives/router_outlet.ts that implements the component creation and destruction logic. The tag triggers the directive's behavior through Angular's selector matching mechanism.
Can I have multiple router outlets in the same component?
Yes, you can create named outlets by adding a name attribute to the tag, such as <router-outlet name="sidebar"></router-outlet>. The primary outlet uses the default name "primary" (or no name attribute). Each outlet can display a different route simultaneously, allowing complex layouts with sidebars, modals, or auxiliary panels without navigating away from the main view.
How do I detect when a component activates or deactivates in a router outlet?
Bind to the (activate) and (deactivate) event outputs on the <router-outlet> element. According to packages/router/src/directives/router_outlet_events.ts, these events emit the component instance being attached or detached. You can also use (attach) and (detach) for cached components that are being reused rather than destroyed, enabling advanced scenarios like route reuse strategies.
Does router-outlet work with lazy-loaded modules?
Yes, the router outlet functions seamlessly with lazy-loaded feature modules. The packages/router/src/config_loader/router_config_loader.ts handles dynamic module loading when a route uses loadChildren. Once loaded, the feature module can define its own child routes and contain nested <router-outlet> elements to render its own sub-components, creating a hierarchical routing tree while maintaining separate code bundles for optimal performance.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →