ismaelramos.dev
  • Search in articles

    Implementing Standalone Components in Angular 15

    Architecture 3 min read
    Angular
    Implementing Standalone Components in Angular 15

    Table of content


    In this article, I’ll walk you through the key parts of building an Angular app with standalone components only. Yes, no NgModule needed.

    All the code is available in this repo, which aims to represent a real-world app. If you’re learning Angular, give it a try and let me know what you think!

    DEMO HERE: https://angular-example-app.onrender.com/

    image of angular logo

    Bootstrap

    The biggest change is in src/main.ts. We need to bootstrap the application differently:

    Before:

    platformBrowserDynamic().bootstrapModule(AppModule);
    

    After:

    import { importProvidersFrom } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import { provideRouter } from '@angular/router';
    ...
    
    bootstrapApplication(AppComponent, {
    providers: [
    importProvidersFrom(HttpClientModule),
    provideRouter([
    {
    path: '',
    component: HomePageComponent,
    pathMatch: 'full',
    },
    { path: '404', component: Error404PageComponent },
    { path: '**', redirectTo: '404' },
    ]),
    ...
    ],
    });
    

    Now we’re using provideRouter and importProvidersFrom. These let us provide routes and pull providers out of modules without importing the modules themselves.

    App Component, but standalone

    After the bootstrap config, we create components with the standalone flag enabled. The app.component.ts looks like this:

    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss'],
      imports: [RouterOutlet, NgIf, ...],
      standalone: true,
    })
    export class AppComponent implements OnInit {}
    

    Notice how we can import other standalone components directly, and even NgModules like ReactiveFormsModule. Other than that, everything inside the component works as before. Here’s another example using other standalone components and modules:

    @Component({
      selector: 'app-edit-profile',
      templateUrl: './edit-profile.component.html',
      standalone: true,
      imports: [ReactiveFormsModule, TrimDirective, FormErrorsComponent, LowercaseDirective, NgIf],
    })
    export class EditProfileComponent implements OnInit {}
    

    Lazy loading routes

    Lastly, here’s how to lazy-load routes. You set it up when defining the bootstrap:

    {
      path: 'auth',
        loadChildren: () => import('./app/modules/auth/auth.routes').then(mod => mod.AUTH_ROUTES),
    }
    

    I’m using a constant called AUTH_ROUTES to hold the auth routes:

    export const authPaths = {
      base: 'auth',
      logIn: 'log-in',
      register: 'register',
      logout: 'logout',
    };
    
    export const authRoutes = {
    logIn: `/${authPaths.base}/${authPaths.logIn}`,
    register: `/${authPaths.base}/${authPaths.register}`,
    logout: `/${authPaths.base}/${authPaths.logout}`,
    };
    
    export const AUTH_ROUTES: Route[] = [
    { path: authPaths.logIn, component: LogInPageComponent, canActivate: [NoAuthGuard] },
    { path: authPaths.register, component: RegisterPageComponent, canActivate: [NoAuthGuard] },
    {
    path: authPaths.logout,
    component: LogoutPageComponent,
    },
    { path: '**', redirectTo: appPaths.error404 },
    ];
    

    This makes it easy to refactor route names later.

    Conclusion

    Remember, there’s a complete real-world app in this repo. Since this post, standalone components became the default in Angular 17, and I revisited the topic in the 2025 guide.

    DEMO HERE: https://angular-example-app.onrender.com/

    I hope you learned something new. If you think this might help other people, please hit the like button so others can read it. ❤️

    If you have any thoughts or questions, feel free to leave a comment!

    Share X / Twitter LinkedIn WhatsApp

    Join the conversation

    No account needed — leave your name and a thought. Comments are reviewed before going live.