How I’ve Replaced Deprecated Resolvers in Angular 16

Get rid of the deprecated implementation of the Resolve<T> class-based data provider in favor of the functional ResolveFn<T>.

Photo by AltumCode on Unsplash

Whenever we wanted to get data based on our parameters/query parameters, we couldn’t consider any better solution than Resolver. It was always a useful mechanism in Angular, providing a nice separation for getting the data and actually handling it within the component.

Resolver assures data availability before navigation ends. Actually, router waits with navigation end event emission until the data is there. Then all you need to do is to subscribe to activatedRoute.data in order to use it within your component directly.

Resolver always had to implement Resolve interface which required (and still is!) resolve method, which was returning either:


Observable<MyDataType> | Promise<MyDataType> | MyDataType

If you’re using Observable pattern to provide the data, make sure your stream completes! Otherwise, you will never see your component!

Class-based resolvers have been already deprecated in the Angular v15 release, but now with version 16, when the functional approach is even more common, it makes sense to switch to the ResolveFn type definition (in case you haven’t done it yet!).

There is no difference in returned type in both approaches. Nothing has changed there. Instead of the class implementation, we will use function/function expression instead.

The benefit of using a functional approach is no need to add created resolver into the providers array!

💡 As an aside, consider using an open-source tool such as Bit to store your reusable Angular components. You can then reuse this component across multiple projects using a simple bit import your.username/yourComponent command.

Learn more:

Overview | Bit

Ok, let’s have a look at the class-based implementation:

import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { Post } from '../models';
import { filter, Observable, take } from 'rxjs';
import { inject } from '@angular/core';
import { PostsFacade } from '../../store/posts';

export class PostResolver implements Resolve<Post> {
constructor(private readonly postsFacade: PostsFacade) {}

resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<Post> {
const id = route.paramMap.get('id');

return this.postsFacade.getOne(id)
.pipe(
filter<Post>((post: Post) => !!post),
take(1));
}
}

ActivatedRouteSnapshot is being used to get the value of id parameter from actual URL. Then, postFacade is being called to get post data I need, making sure, my stream will be closed after the first emitted value. Not to forget to hook it up to the route definition:

  {
path: 'blog/:id',
loadComponent: () => import('./blog/index').then(x => x.PostComponent),
resolve: { post: PostResolver },
},

Let’s compare it with the functional version:

import { ActivatedRouteSnapshot, ResolveFn, RouterStateSnapshot } from '@angular/router';
import { Post } from '../models';
import { inject } from '@angular/core';
import { PostsFacade } from '../../store/posts';
import { filter, take } from 'rxjs';

export const PostResolver: ResolveFn<Post> = (
route: ActivatedRouteSnapshot = inject(ActivatedRouteSnapshot),
state: RouterStateSnapshot = inject(RouterStateSnapshot),
postsFacade: PostsFacade = inject(PostsFacade)
): Observable<Post> => postsFacade.getOne(route.paramMap.get('id'))
.pipe(
filter<Post>((post: Post) => !!post),
take(1)
);

Now, I got rid of the deprecated implementation of Resolve<T> class-based data provider in favor of functional ResolveFn<T>.

Finally, I can use resolved data within PostComponent!

import { Component, inject, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { map, Observable, of } from 'rxjs';
import { Post } from '../../models';
import { AsyncPipe } from '@angular/common';

@Component({
selector: 'app-post',
standalone: true,
templateUrl: './post.component.html',
styleUrls: ['./post.component.scss'],
imports: [AsyncPipe],
})
export class PostComponent implements OnInit {
post$: Observable<Post | null> = of(null);

private readonly route: ActivatedRoute = inject(ActivatedRoute);

ngOnInit(): void {
this.post$ = this.route.data.pipe(map(({ post }) => post));
}
}

Quick and simple right?

Build Angular Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Introduction to Angular | Bit

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

Learn more:


How I’ve Replaced Deprecated Resolvers in Angular 16 was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Bits and Pieces - Medium and was authored by Kamil Konopka

Get rid of the deprecated implementation of the Resolve<T> class-based data provider in favor of the functional ResolveFn<T>.

Photo by AltumCode on Unsplash

Whenever we wanted to get data based on our parameters/query parameters, we couldn’t consider any better solution than Resolver. It was always a useful mechanism in Angular, providing a nice separation for getting the data and actually handling it within the component.

Resolver assures data availability before navigation ends. Actually, router waits with navigation end event emission until the data is there. Then all you need to do is to subscribe to activatedRoute.data in order to use it within your component directly.

Resolver always had to implement Resolve interface which required (and still is!) resolve method, which was returning either:


Observable<MyDataType> | Promise<MyDataType> | MyDataType
If you’re using Observable pattern to provide the data, make sure your stream completes! Otherwise, you will never see your component!

Class-based resolvers have been already deprecated in the Angular v15 release, but now with version 16, when the functional approach is even more common, it makes sense to switch to the ResolveFn type definition (in case you haven’t done it yet!).

There is no difference in returned type in both approaches. Nothing has changed there. Instead of the class implementation, we will use function/function expression instead.

The benefit of using a functional approach is no need to add created resolver into the providers array!

💡 As an aside, consider using an open-source tool such as Bit to store your reusable Angular components. You can then reuse this component across multiple projects using a simple bit import your.username/yourComponent command.

Learn more:

Overview | Bit

Ok, let’s have a look at the class-based implementation:

import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { Post } from '../models';
import { filter, Observable, take } from 'rxjs';
import { inject } from '@angular/core';
import { PostsFacade } from '../../store/posts';

export class PostResolver implements Resolve<Post> {
constructor(private readonly postsFacade: PostsFacade) {}

resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<Post> {
const id = route.paramMap.get('id');

return this.postsFacade.getOne(id)
.pipe(
filter<Post>((post: Post) => !!post),
take(1));
}
}

ActivatedRouteSnapshot is being used to get the value of id parameter from actual URL. Then, postFacade is being called to get post data I need, making sure, my stream will be closed after the first emitted value. Not to forget to hook it up to the route definition:

  {
path: 'blog/:id',
loadComponent: () => import('./blog/index').then(x => x.PostComponent),
resolve: { post: PostResolver },
},

Let’s compare it with the functional version:

import { ActivatedRouteSnapshot, ResolveFn, RouterStateSnapshot } from '@angular/router';
import { Post } from '../models';
import { inject } from '@angular/core';
import { PostsFacade } from '../../store/posts';
import { filter, take } from 'rxjs';

export const PostResolver: ResolveFn<Post> = (
route: ActivatedRouteSnapshot = inject(ActivatedRouteSnapshot),
state: RouterStateSnapshot = inject(RouterStateSnapshot),
postsFacade: PostsFacade = inject(PostsFacade)
): Observable<Post> => postsFacade.getOne(route.paramMap.get('id'))
.pipe(
filter<Post>((post: Post) => !!post),
take(1)
);

Now, I got rid of the deprecated implementation of Resolve<T> class-based data provider in favor of functional ResolveFn<T>.

Finally, I can use resolved data within PostComponent!

import { Component, inject, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { map, Observable, of } from 'rxjs';
import { Post } from '../../models';
import { AsyncPipe } from '@angular/common';

@Component({
selector: 'app-post',
standalone: true,
templateUrl: './post.component.html',
styleUrls: ['./post.component.scss'],
imports: [AsyncPipe],
})
export class PostComponent implements OnInit {
post$: Observable<Post | null> = of(null);

private readonly route: ActivatedRoute = inject(ActivatedRoute);

ngOnInit(): void {
this.post$ = this.route.data.pipe(map(({ post }) => post));
}
}

Quick and simple right?

Build Angular Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Introduction to Angular | Bit

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

Learn more:


How I’ve Replaced Deprecated Resolvers in Angular 16 was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Bits and Pieces - Medium and was authored by Kamil Konopka


Print Share Comment Cite Upload Translate Updates
APA

Kamil Konopka | Sciencx (2023-06-07T06:29:05+00:00) How I’ve Replaced Deprecated Resolvers in Angular 16. Retrieved from https://www.scien.cx/2023/06/07/how-ive-replaced-deprecated-resolvers-in-angular-16/

MLA
" » How I’ve Replaced Deprecated Resolvers in Angular 16." Kamil Konopka | Sciencx - Wednesday June 7, 2023, https://www.scien.cx/2023/06/07/how-ive-replaced-deprecated-resolvers-in-angular-16/
HARVARD
Kamil Konopka | Sciencx Wednesday June 7, 2023 » How I’ve Replaced Deprecated Resolvers in Angular 16., viewed ,<https://www.scien.cx/2023/06/07/how-ive-replaced-deprecated-resolvers-in-angular-16/>
VANCOUVER
Kamil Konopka | Sciencx - » How I’ve Replaced Deprecated Resolvers in Angular 16. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/06/07/how-ive-replaced-deprecated-resolvers-in-angular-16/
CHICAGO
" » How I’ve Replaced Deprecated Resolvers in Angular 16." Kamil Konopka | Sciencx - Accessed . https://www.scien.cx/2023/06/07/how-ive-replaced-deprecated-resolvers-in-angular-16/
IEEE
" » How I’ve Replaced Deprecated Resolvers in Angular 16." Kamil Konopka | Sciencx [Online]. Available: https://www.scien.cx/2023/06/07/how-ive-replaced-deprecated-resolvers-in-angular-16/. [Accessed: ]
rf:citation
» How I’ve Replaced Deprecated Resolvers in Angular 16 | Kamil Konopka | Sciencx | https://www.scien.cx/2023/06/07/how-ive-replaced-deprecated-resolvers-in-angular-16/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.