What’s new in Angular 15?

Angular 15 - New Features
What’s new in Angular 15?

Angular is an open-source framework, also the popular one. It's the first choice for new developers as it offers a host of features that can help to scale a project.

The best part about Angular is that it comes with many updates and features from time to time. And the latest version of the release is Angular 15.

Angular 14 has improved and exciting features, but Angular 15 is all about the platform's proper stability. Let's dive deep to learn what's new in Angular 15.

1. Stable standalone components API

The standalone component was an essential feature of Angular 14, used to build the Angular applications without designing the Ngmodules. In this version, the components have achieved a set degree of stability through different amendments and performance observation.

Also, the Angular community has ensured that with the stability feature, different standalone components will work in sync with Angular elements and HTTP clients. Moreover, you can use the following standalone API to bootstrap your application in a single component.

import {bootstrapApplication} from '@angular/platform-browser';
import {ImageGridComponent} from'./image-grid';

@Component({  
    standalone: true,  
    selector: 'photo-gallery',  
    imports: [ImageGridComponent],  
    template: `    … <image-grid [images]="imageList"></image-grid>  		`,
})

export class PhotoGalleryComponent {  
    // component logic
}

bootstrapApplication(PhotoGalleryComponent);

2. Directive composition API

The directive code can be reused to another level in this version. The feature enables the developers to enhance different host elements with directives and equip Angular with the code reusable strategy, but that is possible with the compiler function. Additionally, directive composition API works with only standalone directives. For instance:

@Component({  
    selector: 'mat-menu',  
    hostDirectives: [HasColor, {    
        directive: CdkMenu,    
        inputs: ['cdkMenuDisabled: disabled'],    
        outputs: ['cdkMenuClosed: closed']  
    }]})

class MatMenu {}

In the above code snippet, you can improve the matmenu with two different directives - cdkmenu and hascolor. Matmenu reuses all the inputs, outputs, and logic.

3. Stable image directory

Angular 15 has introduced a few new features for the image directory. The automatic srcset generation feature ensures that an appropriately sized image is requested by generating the srcset attribute.

However, it can drastically reduce the download times for the images. Apart from this, there is a feature called fill mode. It causes the image to fill the parent container, removing the need to declare the image width and height.

Besides, it is a handy tool if you cannot determine the image size or if you are looking to migrate to the CSS background. You can use the standalone ngoptimised image directive in the module:

import { NgOptimizedImage } from '@angular/common';

// Include it in the necessary NgModule
@NgModule({  
    imports: [NgOptimizedImage],
})
class AppModule {}

// ... or a standalone Component
@Component({  
    standalone: true  
    imports: [NgOptimizedImage],
})
class MyStandaloneComponent {}

Within the component, you can replace the images SRC attribute with ngsrc and ensure you specify the priority attribute.

4. Router default imports

To reduce the load on the router, the router auto unwraps the default exports while lazy loading. For instance, look at the following lazy component:

@Component({  
    standalone: true,  
    template: '...'
})

export default class LazyComponent { ... }

Before the above change, you had to use:

{  
    path: 'lazy',  
    loadComponent: () => import('./lazy-file')
        .then(m => 	m.LazyComponent),
}

Now the router will look for the default export, and if it finds it, it will use it in the auto mode. Moreover, it simplifies the route declaration to:

{  
    path: 'lazy',  
    loadComponent: () => import('./lazy-file'),
}

5. Functional router guards

Take a look at the example where you will be able to define a guard:

@Injectable({ providedIn: 'root' })
export class MyGuardWithDependency implements CanActivate {  
    constructor(private loginService: LoginService) {}  
    
    canActivate() {    
        return this.loginService.isLoggedIn();  
    }
}

const route = {  
    path: 'somePath', 
    canActivate: [MyGuardWithDependency]
};

Here the login service will implement more logic and guard; even though it is simple, you have different boilerplate codes. With the new functional guard, you can reflect the code:

const route = {  
    path: 'admin',  
    canActivate: [() => inject(LoginService).isLoggedIn()]
};

Functional guards are compostable, and you can create factory-like functions. You can accept different configs and return a guard to function.

6. Automatic imports in language service and CLI implements

In the version, the language service can auto-import different components that you will use in the template. Additionally, you can generate a new standalone component with ng g component --standalone.

Here you can simply put the output of ng new. You can reduce the config in the first step by removing the main three elements - test.ts, polyfills.ts, and environments. After which, you can specify Angular in angular.json.

"polyfills": [  
    "zone.js"
]

To reduce config overhead, you can use a .browser list that can allow you to define a target.

7. CDK Listbox

There is a component CDK that offers a set of different primitives for building different UI components. In the V15, they have introduced another primitive that can be customized as per the use case.

The Angular list box modules provide different directives, which help to create customized list-based interactions based on the WAI and ARI list box pattern.

Additionally, by using the @angular/cdk/listbox, you will get the expected behavior for an accessible experience, including layout support, keyboard interaction, and focus management. All the directives apply to their roles to host different elements.

8. Better stack traces

You can get lots of insights from different surveys and use them accordingly. Debugging struggles for Angular developers are real. When partnered with Chrome dev tools, you can fix this:

ERROR Error: Uncaught (in promise): Error
Error
at app.component.ts:18:11
at Generator.next (<anonymous>)
at asyncGeneratorStep (asyncToGenerator.js:3:1)
at _next (asyncToGenerator.js:25:1)
at _ZoneDelegate.invoke (zone.js:372:26)
at Object.onInvoke (core.mjs:26378:33)
at _ZoneDelegate.invoke (zone.js:371:52)
at Zone.run (zone.js:134:43)
at zone.js:1275:36
at _ZoneDelegate.invokeTask (zone.js:406:31)
at resolvePromise (zone.js:1211:31)
at zone.js:1118:17
at zone.js:1134:33

The above code suffers from two main issues. A single line corresponds to the code the developer has used. Also, a lot of things come from third-party dependency.

There is no information about what caused the interaction error. But by making some changes, the stack changes can be improved.

To sum up,

There are many other changes in Angular version 15 you can try. It also depends on what project you are working on. The new stable update will surely be a game-changer in the development process. So you must hire an angular developer to leverage the technology and get in-depth knowledge about the version.