3

I'm using the router resolver in order to fetch my ngrx store data before the page is loaded. After inserting the resolver into my routes, the router is not generating the content I have in

<router-outlet></router-outlet>

Other routes (without the resolver) working good, and if I erase the resolver form the route the page is loading just fine.

My resolver file:

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Store } from '@ngrx/store';

import { MenuItem } from '../navbar/menuItem.model';

import * as fromApp from '../store/app.reducer';

@Injectable()
export class MenuItemsResolver implements Resolve<MenuItem[]> {
    constructor(
        private store: Store<fromApp.AppState>
    ) {}

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
        Observable<MenuItem[]> | Promise<MenuItem[]> | MenuItem[]
    {
        return this.store.select('menuItems').pipe(
            map((data: { menuItems: MenuItem[] }) => data.menuItems)
        );
    }
}

Routes:

const appRoutes: Routes = [
    { path: '', component: HomeComponent, resolve: {menuItems: MenuItemsResolver} },
    { path: 'portfolio', component: ProjectsComponent },
    { path: 'portfolio/:project', component: ProjectComponent },
    { path: '404', component: PageNotFoundComponent },
    { path: '**', redirectTo: '404' }
];

Subscription to route data in the HomeComponent:

this.route.data.subscribe((data: Data) => this.menuItems = data['menuItems']);

(Notice that I've tried to erase this line to check if the problem is here and It still occur)

The problem is solved only if I deleted the resolver from my routes in app-routing.module.ts

Ron Rofe
  • 738
  • 1
  • 9
  • 25
  • use `tap()` operator to see if any value is emitted upon activating the resolver. Also use `take(1)` or `first()` operator which will ensure the stream is completed as soon as first value has been emitted. – Alexus Nov 05 '19 at 12:50

1 Answers1

5

Resolver waits until the Observable closes, but the state selectors do not close. You need to close the Observable manually using the first operator, which closes the stream after the first value.

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { map, first } from 'rxjs/operators';
import { Store } from '@ngrx/store';

import { MenuItem } from '../navbar/menuItem.model';

import * as fromApp from '../store/app.reducer';

@Injectable()
export class MenuItemsResolver implements Resolve<MenuItem[]> {
    constructor(
        private store: Store<fromApp.AppState>
    ) {}

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
        Observable<MenuItem[]> | Promise<MenuItem[]> | MenuItem[]
    {
        return this.store.select('menuItems').pipe(
            map((data: { menuItems: MenuItem[] }) => data.menuItems),
            first()
        );
    }
}
izmaylovdev
  • 1,828
  • 8
  • 16