Fundamentals
Standalone Components
Master Angular Standalone Components, covering imports lists, bootstrapping logic, NgModule elimination, and lazy-loading routes.
1. Learning Objectives
In this lesson, you will master Angular Standalone Components. By the end of this topic, you will be able to:
- Explain why standalone components are preferred over NgModule-based components.
- Declare components using the
standalone: trueflag. - Manage dependencies using the component-level
importsarray. - Bootstrap an application using
bootstrapApplicationinstead of module-based bootstrapping. - Lazy-load standalone components in routing configurations.
2. Overview
Standalone components (introduced in Angular 14) simplify application structure by reducing the need for NgModules. Instead of registering components inside a central module, standalone components declare their dependencies directly in their own metadata config. This makes them independent, modular, and easy to build and test.
3. Why This Topic Matters
Standalone components simplify development and improve performance:
- Simplifies Application Structure: In legacy Angular apps, every component had to be registered in an
NgModuledeclarations array. This required maintaining complex module files and led to circular dependency errors. Standalone components manage their own dependencies, reducing boilerplate code. - Unlinked Dependencies Bug: If a standalone component template uses features from another component or directive (such as
NgIfor a custom card component) but forgets to import it in itsimportsarray, compilation will fail. The component must declare its dependencies explicitly.
4. Real-World Analogy
Think of standalone components like **camping appliances that contain their own fuel canisters**:
- Module-based (Central Gas Line): Every appliance (stove, lantern, heater) must connect to a central utility line in the camp. If you move an appliance, you must re-plumb the gas lines.
- Standalone (Self-Powered): The camping stove has its own butane canister attached (the
importsarray). You can pick it up and move it anywhere, and it works instantly because it carries its fuel source with it.
5. Core Concepts
Standalone components introduce three main structural changes:
- standalone: true: A metadata flag in the
@Componentdecorator that marks the component as standalone. - imports array: Declares the component's dependencies (other standalone components, directives, pipes, or modules) directly in its metadata.
- bootstrapApplication(): A bootstrap method that runs standalone components directly from
main.ts, bypassingNgModulebootstrapping.
| Property | NgModule-based Component | Standalone Component |
|---|---|---|
| Registration | Must be registered in an NgModule declarations array. |
Self-declared. Set standalone: true in component metadata. |
| Dependencies | Inherited from imports declared in its parent module. | Declared explicitly in the component's imports array. |
| Lazy Loading | Requires lazy-loading the parent module. | Lazy-loaded directly using the loadComponent router option. |
6. Syntax & API Reference
Below is a standalone component that imports the CommonModule (for structural directives like ngIf) and a child component:
7. Visual Diagram
This diagram displays how standalone component dependencies compare to module-based components:
8. Live Example — Full Working Code
Below is the main.ts bootstrap file showing how to launch an application using a standalone root component:
9. Interactive Playground
Try It Yourself Challenges:
- Add a new component to the dashboard template and register it in the
importsarray. - Test what happens if you use a directive (like
*ngIf) in the template but omitCommonModulefrom the imports list.
10. Common Mistakes
| Mistake | Why it happens | Wrong | Correct |
|---|---|---|---|
| Forgetting dependency imports | Using other components or directives inside the template but forgetting to declare them in the component's imports list, causing template rendering errors. | imports: [] (template uses <app-avatar>) |
imports: [AvatarComponent] |
| Registering standalone components in modules | Declaring standalone components in an NgModule's declarations array. Standalone components must be imported inside the imports array. | declarations: [StandaloneComponent] |
imports: [StandaloneComponent] |
11. Best Practices
- Use standalone by default: Write new components, directives, and pipes as standalone elements.
- Import only necessary dependencies: Declare only the specific components or directives needed in the component's
importsarray. Avoid importing entire modules (likeCommonModule) if you only need a single directive. - Lazy-load standalone components: Lazy-load routes directly using the
loadComponentrouter configuration option:{ path: 'user', loadComponent: () => import('./user.component').then(m => m.UserComponent) }.
12. Browser Compatibility/Requirements
Standalone components compile down to standard JS and do not affect browser compatibility. They are supported in Angular version 14+.
13. Interview Questions
🟢 Q1: How do you lazy-load a standalone component in the Angular Router?
Answer: Use the loadComponent property in the router configuration and pass an import expression that resolves to the component class (e.g. loadComponent: () => import('./profile.component').then(m => m.ProfileComponent)).
14. Debugging Exercise
Identify and fix the compiler error in this standalone component declaration:
Diagnosis: The template uses the *ngIf directive, but the component has an empty metadata imports configuration. Since it is a standalone component, it does not inherit dependencies from a parent module. To fix this, import NgIf or CommonModule in the component's imports array.
Fixed component:
15. Practice Exercises
Exercise 1: Building a Profile card
Build a standalone component named `profile-card` that displays a user's name and bio, and import it into your root component.
16. Scenario-Based Challenge
The Module-to-Standalone Migration Challenge:
An existing Angular app contains 15 shared component declarations registered in a single `SharedModule`. The module is loaded globally, increasing bundle size and slowing down page loads. Propose an implementation plan to refactor these components to standalone models to support lazy loading.
17. Quick Quiz
Q1: In which metadata parameter should you declare standalone components that are used inside other standalone components?
A) declarations
B) providers
C) imports
Answer: C — Standalone components declare their dependencies directly in their own metadata imports array.
18. Summary & Key Takeaways
- • Standalone components manage their own dependencies, reducing template boilerplate and NgModule code.
- • Lazy-load routes directly using the loadComponent router configuration option.
19. Cheat Sheet
| Metadata Option | Purpose |
|---|---|
standalone: true |
Marks the component as standalone, allowing it to declare dependencies in its own imports array. |