What Is New in Angular 15.0
Angular 15.0 delivers a significant set of improvements focused on developer experience, performance, and stability. The release includes a stable standalone APIs, directive composition, and an improved image directive.
| Category | Key Changes |
|---|---|
| New Features | Stable standalone APIs, Directive composition API, Stable image directive |
| Improvements | CDK Listbox, Router unwraps default imports, Functional router guards |
| Deprecations | Reflective injector APIs, `RouterLinkWithHref` directive |
| Bug Fixes | Over 25 fixes across common, compiler, compiler-cli, and more |
Are Standalone APIs Now Stable?
Yes, the standalone APIs have graduated from developer preview to a stable feature. You can now bootstrap an application using a standalone component without the need for an NgModule. This simplifies the initial project structure and reduces boilerplate.
You create a standalone component by setting standalone: true in its decorator. The Angular CLI can also generate standalone components and directives directly using the --standalone flag. In practice, this means less code to maintain and a clearer mental model for building features.
Bootstrapping a Standalone Application
import {bootstrapApplication} from '@angular/platform-browser';
import {ImageConfig} from '@angular/common';
import {AppComponent} from './app/app.component';
bootstrapApplication(AppComponent, {
providers: [
{provide: ImageConfig, useValue: {disableImageSizeWarning: true, disableImageLazyLoadWarning: true}}
]
});
What is the Directive Composition API?
The new directive composition API allows you to apply directives to a component's host element from within the component class. This is a powerful feature for creating reusable component behaviors that were previously harder to implement.
You use the hostDirectives property in the component decorator to specify an array of directives. The compiler will then apply these directives to the host element, including their inputs and outputs. This matters because it enables better code reuse and composition of behavior.
Using hostDirectives
@Component({
selector: 'app-menu',
hostDirectives: [HasColor, {
directive: CdkMenu,
inputs: ['cdkMenuDisabled: disabled'],
outputs: ['cdkMenuClosed: closed']
}],
template: `...`
})
export class MenuComponent {}
How Has the Image Directive Improved?
The NgOptimizedImage directive is now stable. It includes new functionality for automatically generating a preconnect link for your image's domain, which can improve loading performance.
To use it, replace your src attribute with ngSrc and ensure the width and height are set. The directive also provides more granular control over image optimization and a cleaner API for setting up loaders.
What Router Improvements Were Made?
The router now automatically unwraps default exports when using lazy loading. This removes a common pain point where developers had to remember to target the default export explicitly in the loadChildren callback.
Router guards can now be written as simple JavaScript functions. This functional approach is cleaner and more tree-shakable than the class-based guard interface. You can now export a function and reference it directly in your route configuration.
Functional Router Guards
const route = {
path: 'admin',
canActivate: [() => inject(LoginService).isLoggedIn()],
loadChildren: () => import('./admin/routes'),
};
What APIs Have Been Deprecated?
The reflective injector APIs are now deprecated. This includes ReflectiveInjector and related symbols. You should use the Injector.create API instead for creating injectors dynamically.
The RouterLinkWithHref directive has been deprecated. Use the standard RouterLink directive for all cases, as it now handles elements both with and without an href attribute.
FAQ
Do I have to use standalone components now?
No, standalone components are optional. The NgModule system remains fully supported and is not deprecated. You can adopt standalone components incrementally.
How do I try out the new Directive Composition API?
Add the hostDirectives property to a component decorator. List the directives you want to apply to the host element, and optionally remap their inputs and outputs.
What's the benefit of functional router guards?
Functional guards are simpler to write and test. They are also more tree-shakable, which can help reduce your application's final bundle size.
I use lazy loading; what does "unwrapping default imports" mean for me?
It means you can simplify your route definitions. You no longer need to write () => m.MyModule for a default export; the router will now automatically handle () => import('./my.module').
Is the CDK Listbox accessible?
Yes, the CDK Listbox is designed according to the WAI-ARIA listbox pattern, providing built-in keyboard navigation and focus management for building accessible list interfaces.