I am following along with the Angular course, but the video uses the resolve class which is now deprecated and not available in Angular 17. I have reviewed a few different articles, but I am not able to get it to return the data as the course is expecting.
Below is the code from the class
I tried following along with other articles and changing it from a class to a const, but I'm having trouble understanding how to return the call on the fetch recipes method.
Below is the modified code:
import { Recipe } from "./recipe.model";
import { DataStorageService } from "../shared/data-storage.service";
@Injectable({providedIn: 'root'})
export const RecipesResolverService: ResolveFn<Recipe[]> =
(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
const dataStorageService = inject(DataStorageService);
return this.dataStorageService.fetchRecipes();
}
Below is the data-storage.service.ts that the above was referred to:
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { map, tap } from "rxjs/operators";
import { Recipe } from "../recipes/recipe.model";
import { RecipeService } from "../recipes/recipe.service";
@Injectable({ providedIn: 'root' })
export class DataStorageService {
constructor(private http: HttpClient, private recipesService: RecipeService) { }
storeRecipes() {
const recipes = this.recipesService.getRecipes();
this.http.put(
'https://ng-course-recipe-book-af2f9-default-rtdb.firebaseio.com/recipes.json',
recipes
)
.subscribe(response => {
console.log(response);
});
}
fetchRecipes() {
return this.http
.get<Recipe[]>(
'https://ng-course-recipe-book-af2f9-default-rtdb.firebaseio.com/recipes.json'
)
.pipe(
map(recipes => {
return recipes.map(recipe => {
return {
...recipe,
ingredients: recipe.ingredients ? recipe.ingredients : []
};
});
}),
tap(recipes => {
this.recipesService.setRecipes(recipes);
})
)
}
}
And below is the app-routing.module.ts file, with resolve used in the RecipeDetail and Edit components:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { RecipesComponent } from './recipes/recipes.component';
import { ShoppingListComponent } from './shopping-list/shopping-list.component';
import { RecipeStartComponent } from './recipes/recipe-start/recipe-start.component';
import { RecipeDetailComponent } from './recipes/recipe-detail/recipe-detail.component';
import { RecipeEditComponent } from './recipes/recipe-edit/recipe-edit.component';
import { RecipesResolverService } from './recipes/recipes-resolver.service';
const appRoutes: Routes = [
{path: '', redirectTo: '/recipes', pathMatch: 'full'},
{ path: 'recipes', component: RecipesComponent, children: [
{ path: '', component: RecipeStartComponent},
{ path: 'new', component: RecipeEditComponent},
{ path: ':id', component: RecipeDetailComponent, resolve: [RecipesResolverService]},
{ path: ':id/edit', component: RecipeEditComponent, resolve: [RecipesResolverService]}
]},
{ path: 'shopping-list', component: ShoppingListComponent},
];
@NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Please let me know what I am doing wrong. all of the articles I have looked at seem to take different approaches. Below are a link to the few I looked at:
https://medium.com/codex/functional-resolvers-in-angular-43951c50c4e https://blog.bitsrc.io/how-ive-replaced-deprecated-resolvers-in-angular-16-59811f79cd5b https://angularjobs.com/curated/how-ive-replaced-deprecated-resolvers-in-angular-16-59811f79cd5b-on-blog-bitsrc-io
Below are the list of changes to be done.
When working with resolverFn you do not need @Injectable(...)
since it's only meant for a service and not a function:
import { Recipe } from "./recipe.model";
import { DataStorageService } from "../shared/data-storage.service";
export const RecipesResolverService: ResolveFn<Recipe[]> = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
const dataStorageService = inject(DataStorageService);
return this.dataStorageService.fetchRecipes();
}
Then you can try importing the resolver, as a property of an object instead:
...
{ path: ':id', component: RecipeDetailComponent, resolve: { data: RecipesResolverFn } },
{ path: ':id/edit', component: RecipeEditComponent, resolve: { data: RecipesResolverFn } }
...
Then we can subscribe to get the data:
...
constructor(private activatedRoute: ActivatedRoute) { }
ngOnInit() {
this.activatedRoute.data.pipe(map(data => data['data'])).subscribe((response: any) => {
// use the data
});
...