Write Angular like a pro. Angular Icon

Follow the ultimate Angular roadmap.

Setup Standalone Components with Angular's Router

In Angular v15 we finally saw the introduction of standalone components.

With @NgModule being an optional choice, this brings some changes as to how we create routes and routing definitions.

There is also lazy loading standalone components to consider.

But before we get there, how can we create routes with standalone components in Angular?

First we need to bootstrap the Angular application. I’ve already written an in-depth guide to bootstrapping a standalone Angular app so we won’t go into things too deep, we’ll just cover what we need.

Let’s start with a simple App component and bootstrap it via bootstrapApplication:

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';

@Component({
  selector: 'my-app',
  standalone: true,
  template: `
    Hello Angular!
  `,
})
export class App {}

bootstrapApplication(App);

Before standalone components, we would use the RouterModule.forRoot() method and pass in our routing configuration.

So, how do we migrate across to the new standalone style whilst maintaining our routing?

Let’s assume we have the following routes:

import { Route } from '@angular/router';
import { ProductsComponent } from '../products.component';
import { ProductComponent } from './product.component';

export const routes: Route[] = [
  {
    path: '',
    component: ProductsComponent,
  },
  {
    path: ':id',
    component: ProductComponent,
  },
  {
    path: '**',
    redirectTo: '',
  },
];

We now need to import a new function provideRouter and pass it into the providers on the bootstrapApplication call:

import { Component } from '@angular/core';
import { provideRouter } from '@angular/router';
import { bootstrapApplication } from '@angular/platform-browser';

import { routes } from './routes';

@Component({
  selector: 'my-app',
  standalone: true,
  template: `
    Hello Angular!
  `,
})
export class App {}

bootstrapApplication(App, {
  providers: [provideRouter(routes)],
});

💯 Using provideRouter is the “standalone way”, which avoids importing RouterModule entirely. For all Directives that the RouterModule would expose, you need to import them per standalone component.

That’s great for now, but we need a <router-outlet> now to render our components!

As we’re using standalone components, we’ll need to import the RouterOutlet directive and add it to the component imports metadata:

import { Component } from '@angular/core';
import { provideRouter, RouterOutlet } from '@angular/router';
import { bootstrapApplication } from '@angular/platform-browser';

import { routes } from './routes';

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [RouterOutlet],
  template: `
    <router-outlet></router-outlet>
  `,
})
export class App {}

bootstrapApplication(App, {
  providers: [provideRouter(routes)],
});

What I love about this new way to provide routing is that we don’t need to create an @NgModule for every single routing configuration. So if you’ve been doing that, it’s time to refactor!

Here’s a live code example for you to try out:

And that’s it! You can pass in your routes into provideRouter which makes them available to our app - just don’t forget to import your RouterOutlet and any other directives you’re using.

🏆 Check out my brand new Angular v15 course where you’ll learn Angular, TypeScript, RxJS and state management principles from beginning to expert level.

Happy routing!

Learn Angular the right way.

The most complete guide to learning Angular ever built.
Trusted by 82,951 students.

Todd Motto

with Todd Motto

Google Developer Expert icon Google Developer Expert

Related blogs 🚀

Free eBooks:

Angular Directives In-Depth eBook Cover

JavaScript Array Methods eBook Cover

NestJS Build a RESTful CRUD API eBook Cover