I defined a resolver in my Angular (v13) app to do some shenanigans with a wordpress backend. When the user accesses an URL I want the resolver to check post type and ID from wordpress and route accordingly (post list, single post, page, ...).
To do that I have injected Angular's Router in my WordpressResolver class, but when I call router.navigate(...)
I get the following error :
ERROR TypeError: Cannot read properties of undefined (reading 'navigate')
It seems like the router is not injected, but I cannot figure out why. I added the @Injectable decorator on my resolver and provided it in the routing module.
Here are my routing module and resolver code.
app.module.routing.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NotFoundComponent } from './modules/not-found/not-found.component';
import { WordpressResolver } from './wordpress-resolver';
const routes: Routes = [
{
path: 'posts',
loadChildren: () =>
import('./modules/posts/posts.module').then((m) => m.PostsModule),
},
{
path: 'single/:id',
loadChildren: () =>
import('./modules/post/post.module').then((m) => m.PostModule),
},
{
path: 'page/:id',
loadChildren: () =>
import('./modules/page/page.module').then((m) => m.PageModule),
},
{
path: '**',
component: NotFoundComponent,
resolve: {
error: WordpressResolver,
},
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [WordpressResolver],
})
export class AppRoutingModule {}
wordpress-resolver.ts
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import {
ActivatedRouteSnapshot,
Resolve,
Router,
RouterStateSnapshot,
} from '@angular/router';
import { environment } from 'src/environments/environment';
import { UrlData } from './shared/model/url-data.interface';
import { UrlType } from './shared/model/url-type.enum';
@Injectable({ providedIn: 'root' })
export class WordpressResolver implements Resolve<HttpErrorResponse | null> {
constructor(private http: HttpClient, private router: Router) {}
private error: HttpErrorResponse | null = null;
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): HttpErrorResponse | null {
this.http
.get<UrlData>(environment.domain + state.url)
.subscribe(this.resolveSuccess, this.resolveError);
return this.error;
}
private resolveSuccess(urlData: UrlData): void {
switch (urlData.type) {
case UrlType.POSTS:
this.router.navigate(['/posts'], { skipLocationChange: false });
return;
case UrlType.POST:
this.router.navigate(['/post', urlData.id], {
skipLocationChange: false,
});
return;
case UrlType.PAGE:
this.router.navigate(['/page', urlData.id], {
skipLocationChange: false,
});
return;
default:
return;
}
}
private resolveError(error: HttpErrorResponse): void {
this.error = error;
this.router.navigate(['/error'], {
skipLocationChange: true,
});
}
}
(I know '/error' is not mapped yet, this is a work in progress)
You have to define your callback function as arrow function so that you can access global scope
resolveSuccess= (urlData: UrlData): void => { }