Angular Standalone Components
This article discusses the latest feature in Angular called standalone components. Traditionally, developers had to create or update an existing NgModule
to use a newly created component. NgModules
were used to specify the available components, directives, and pipes for templates. However, with the new standalone
API, it is now possible to write Angular components, directives, and pipes without creating an associated NgModule
.
What are Standalone Components?
Standalone components are self-contained and manage their template dependencies, making NgModule
optional for many development tasks. This shift towards standalone components simplifies the learning journey and reduces the amount of code and files required. The benefits of this new approach are significant. Creating a new component becomes easier with less code to write and fewer files to modify. Moreover, it reduces the number of concepts developers need to understand, making Angular more approachable.
Most importantly, standalone components can be packaged, reused, and lazily loaded independently, enabling new use cases that were previously challenging or even impossible.
To demonstrate the new APIs, let's go over the new features step-by-step -
The standalone flag and component imports
Components, directives, and pipes can now be marked as standalone: true
. Angular classes marked as standalone do not need to be declared in an NgModule
. Standalone components specify their dependencies directly inside it instead of specifying them through NgModules
. It can directly import other standalone components, directives, and pipes.
@Component({
standalone: true, // this makes it a standalone component
selector: 'standalone-component',
imports: [OtherStandaloneComponent],
// other standalone components or dependencies can be imported
template: `
... <other-standalone-component></other-standalone-component>
`,
})
export class StandaloneComponent {
// component logic
}
imports
can also be used to reference standalone directives and pipes. In this way, standalone components can be written without the need to create an NgModule
to manage template dependencies.
Using existing NgModules in a Standalone Component
When writing a standalone component, you may want to use other components, directives, or pipes in the component's template which are not marked as standalone but instead declared and exported by an existing NgModule
. In this case, you can import the NgModule
directly into the standalone component:
@Component({
standalone: true,
selector: 'my-app',
// an existing module is imported directly into a standalone component
imports: [MatButtonModule],
template: `
...
<button mat-button>Next Page</button>
`,
})
export class AppComponent {
// component logic
}
Using standalone components in NgModule-based applications
Standalone components can also be imported into existing NgModules-based contexts. This allows existing applications to incrementally adopt the new standalone style of component.
@NgModule({
declarations: [AppModule],
exports: [AppComponent],
imports: [StandaloneComponent],
//standalone component can be imported the same way as normal components
})
export class AppModule {}
Bootstrapping app with standalone component
An Angular application can be bootstrapped without any NgModule
by using a standalone component. This component can be used as the application root component. This can be achieved using bootstrapApplication
API:
// in the main.ts file
import {bootstrapApplication} from '@angular/platform-browser';
import {MainComponent} from './app/main.component';
bootstrapApplication(MainComponent);
Configuring dependency injection
When bootstrapping an application, we can configure Angular’s dependency injection and provide configuration values or services to be used throughout the application. Add these services and values as providers to bootstrapApplication
.
bootstrapApplication(MainComponent, {
providers: [
{provide: BACKEND_URL, useValue: 'https://...'},
{provide: ErrorHandler, useClass: GlobalErrorHandler}
// ...
]
});
If a library only offers an NgModule
API for its DI configuration, you can use the importProvidersFrom
utility to still use it with bootstrapApplication
and other standalone contexts
import {LibraryModule} from 'library';
bootstrapApplication(AppComponent, {
providers: [
{provide: ErrorHandler, useClass: GlobalErrorHandler},
// ...
importProvidersFrom(
LibraryModule.forRoot() // from module based library
),
]
});
Summary
We have now successfully created standalone components, managed their template dependencies. We have also seen how other module-based library or dependency can be included in standalone components and how it is used with the existing module-based applications. In the next article we learn about routing to navigate between pages rendered by standalone components. These new functionalities and APIs are available from Angular version 14 onwards and are fully compatible with existing Angular applications, requiring no rewrites or breaking changes.
Subscribe to my newsletter
Read articles from Om Dhanwant directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Om Dhanwant
Om Dhanwant
Hi! I am a software developer. I have a proven experience of working as a Frontend developer in various product based companies. I have successfully delivered enterprise applications which are used by thousands of people. I am passionate about exploring new technologies and always ready to learn something new every day!