I'm having an Angular 7 issue where a module's child components that have a resolver on the route don't load.
app-routing.module.ts
{
path: 'Account',
loadChildren: './account/account.module#AccountModule'
}
account-routing.module.ts
{
path: 'Profile',
component: ProfileComponent,
resolve: {
profile: ProfileResolver
}
}
profile.resolver.ts
@Injectable()
export class ProfileResolver implements Resolve<Profile> {
constructor(private readonly accountService: AccountService) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Profile> {
return this.accountService.profile();
}
}
profile.component.ts
@Component({
⋮
})
export class ProfileComponent implements OnInit {
model: Profile;
constructor(private readonly route: ActivatedRoute) {
}
ngOnInit(): void {
this.model = this.route.snapshot.data['profile'] as Profile;
}
}
account.service.ts
@Injectable()
export class AccountService {
constructor(protected readonly http: HttpClient) {
}
profile(): Observable<Profile> {
return this.http.get<Profile>(`${environment.apiUrl}/Account/Profile`);
}
}
The behavior is that, when navigating to /Account/Profile
, the ProfileResolver
is called, hits the server, and gets a 200 response with the Profile
object (I can see it in the Network tab), and then... nothing. Neither the constructor
or the ngOnInit
method of ProfileComponent
are called.
If I remove the ProfileResolver
from the AccountRoutingModule
and call the AccountService
directly from the ngOnInit
method, it works. But there are a number of template parse errors from the template while it waits for the response (which is the whole reason I want to use the resolve
).
Is there something extra I need to do to make a resolver work with these modules?
This might also be the same issue as described here: Angular Router don't load component with resolver
UPDATE: I turned on enableTracing
so I could see what is happening. Here is the output:
Router Event: NavigationStart
NavigationStart(id: 2, url: '/Account/Profile')
NavigationStart {id: 2, url: "/Account/Profile", navigationTrigger: "imperative", restoredState: null}
Router Event: RoutesRecognized
RoutesRecognized(id: 2, url: '/Account/Profile', urlAfterRedirects: '/Account/Profile', state: Route(url:'', path:'') { Route(url:'Account', path:'Account') { Route(url:'Profile', path:'Profile') } } )
RoutesRecognized {id: 2, url: "/Account/Profile", urlAfterRedirects: "/Account/Profile", state: RouterStateSnapshot}
Router Event: GuardsCheckStart
GuardsCheckStart(id: 2, url: '/Account/Profile', urlAfterRedirects: '/Account/Profile', state: Route(url:'', path:'') { Route(url:'Account', path:'Account') { Route(url:'Profile', path:'Profile') } } )
GuardsCheckStart {id: 2, url: "/Account/Profile", urlAfterRedirects: "/Account/Profile", state: RouterStateSnapshot}
Router Event: ChildActivationStart
ChildActivationStart(path: '')
ChildActivationStart {snapshot: ActivatedRouteSnapshot}
Router Event: ActivationStart
ActivationStart(path: 'Profile')
ActivationStart {snapshot: ActivatedRouteSnapshot}
Router Event: GuardsCheckEnd
GuardsCheckEnd(id: 2, url: '/Account/Profile', urlAfterRedirects: '/Account/Profile', state: Route(url:'', path:'') { Route(url:'Account', path:'Account') { Route(url:'Profile', path:'Profile') } } , shouldActivate: true)
GuardsCheckEnd {id: 2, url: "/Account/Profile", urlAfterRedirects: "/Account/Profile", state: RouterStateSnapshot, shouldActivate: true}
Router Event: ResolveStart
ResolveStart(id: 2, url: '/Account/Profile', urlAfterRedirects: '/Account/Profile', state: Route(url:'', path:'') { Route(url:'Account', path:'Account') { Route(url:'Profile', path:'Profile') } } )
ResolveStart {id: 2, url: "/Account/Profile", urlAfterRedirects: "/Account/Profile", state: RouterStateSnapshot}
So it looks like the ResolveEnd
event is never firing. I found this issue: Router's ActivatedRoute data
returns empty {} if module is lazy. It seems like it may be related but I'm not sure how I would implement that fix here.
Include AuthGuard to Route Now for each request of the route, the verify() function will be called and if the verify() function returns true, then only we can access the particular route. If it returns false, we are not able to access it. This is how we can restrict the routes from unauthorized user access.
This generally occurs when there is a mismatch in the routes specified, or a component which is not present in our routing configuration, or if there is the use of multiple routes in our angular application which is not properly configured.
Angular Route Resolver is used for pre-fetching some of the data when the user is navigating from one route to another. It can be defined as a smooth approach for enhancing user experience by loading data before the user navigates to a particular component.
Well, there is a difference, the canActivate exists to prevent unauthorized users from accessing a route, while canLoad is used to prevent the application from loading an entire module or component in a lazy way (lazy loading) if the user is not authorized.
I consulted the Routing & Navigation guide again and changed my Resolver to look like it does there:
profile.resolver.ts
@Injectable()
export class ProfileResolver implements Resolve<Profile> {
constructor(private readonly accountService: AccountService) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Profile> {
return this.accountService.profile().pipe(
take(1),
map((profile: Profile) => profile));
}
}
The key was adding the take(1)
. Without this, the ResolveEnd
event is never fired and the Router
just hangs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With