23 Jun 2022
3 min

Angular v14 – What you should know?

Exactly on the 2nd of June, the latest, fourteenth version of Angular had its premiere. In this article we will look at the most important changes, which you will find in ng14. Read on to find out more.

Standalone components

A long-awaited feature has been included in version 14 of our beloved framework. On the one hand, it is an answer to the criticism that the framework struggled with for many years, as being too difficult for beginners, and angular modules were pointed out as one of the main reasons. On the other hand, we can be sure that this change will bring us a lot of new improvements, exciting ways and examples of using this functionality. 

From now on we can create our components, directives and pipes as standalones by setting the “standalone” flag to true in their decorators.

@Component({
  standalone: true,
  selector: 'photo-gallery',
  imports: [ImageGridComponent, MatButtonModule],
  template: `
    ... <image-grid [images]="imageList"></image-grid>
  `,
})
export class PhotoGalleryComponent {
  // component logic
}

As you can see in the example above, analogous to a module, the above-mentioned decorator takes imports, inside of which there can be other “standalone components” (ImageGridComponent) or whole modules (MatButtonModule – as is the case with the module decorator). Standalone components can also be imported by modules.

The introduction of the above changes does not have to mean a complete departure from modules, because they were originally implemented in Angular to help us organize applications into coherent functional blocks. We can still come across examples where using a module may make sense. This can be especially true for libraries. Based on the example below, both ImageCarouselComponent and ImageSlideComponent need to be present in the theme to ensure that the image carousel that runs on this component works properly.

@NgModule({
  imports: [ImageCarouselComponent, ImageSlideComponent],
  exports: [ImageCarouselComponent, ImageSlideComponent],
})
export class CarouselModule {}

This isn’t the only consequence of this change, it also affects other areas of our application, including routing.

Routing

We have the possibility of lazy loading of standalone components.

export const ROUTES: Route[] = [
  {path: 'admin', loadComponent: () => import('./admin/panel.component').then(mod => mod.AdminPanelComponent)},
  // ...
];

The above example only works if the AdminPanelComponent is standalone. This isn’t the end of the changes in this area. There are many indications that the new approach to defining routing, will result in the fact that it can become the heart of our application and in many cases be responsible for what services will be available to us under a given route, because from now on we can also define providers here (the equivalent of providers from modules).

export const ROUTES: Route[] = [
  {
    path: 'admin',
    providers: [
      AdminService,
      {provide: ADMIN_API_KEY, useValue: '12345'},
    ],
    children: [
      path: 'users', component: AdminUsersComponent,
      path: 'teams', component: AdminTeamsComponent,
    ],
  },
];

AdminService and ADMIN_API_KEY will only be available to route ‘admin’ and his children.

Page Title

We have also been given the ability to set the title for our pages at our route level. Previously, we had to set it manually by injecting the Title service and then calling the setTitle() method. From now on we can set this value at the level of our routing definition.

const routes: Routes = [{
  path: 'home',
  component: HomeComponent
  title: 'My App - Home'  // <-- Page title
}, {
  path: 'about',
  component: AboutComponent,
  title: 'My App - About Me'  // <-- Page title
}];

Typed Forms

Another very long awaited feature. The issue regarding this change was written in 2016! From now on we can type our forms. The new Api will ensure that the values in our controls, groups and arrays are TYPE SAFE. As well as the change itself being great, Angular has also made sure that we can migrate gradually, without having to worry about messing up our existing forms. After running ng update, our version 13 form will take the form shown in the example below of Angular FormGroup.

// v13 untyped form
const cat = new FormGroup({
   name: new FormGroup(
      first: new FormControl('Barb'),
      last: new FormControl('Smith'),
   ),
   lives: new FormControl(9)
});

// v14 untyped form after running `ng update`
const cat = new UntypedFormGroup({
   name: new UntypedFormGroup(
      first: new UntypedFormControl('Barb'),
      last: new UntypedFormControl('Smith'),
   ),
   lives: new UntypedFormControl(9)
});

All existing models will be changed to their respective created by adding the prefix Untyped. This is to allow us to type individual forms incrementally and migrate safely. Most importantly, from now on, you can expect the following prompts from your IDE when working with a correctly populated form ? ? ?

Playground

Using protected fields in a template

And at the end, a little something. We got the possibility to use fields marked as protected in the template.

@Component({
  selector: 'my-component',
  template: '{{ message }}',  // Now compiles!
})
export class MyComponent {
  protected message: string = 'Hello world';
}

There are more changes and improvements. You can find the full pool in the changelog and on the official Angular blog. Let me know in the comments if any of these changes you were particularly looking forward to! ?

Share this post

Sign up for our newsletter

Stay up-to-date with the trends and be a part of a thriving community.