Search code examples
angularangular6angular-routing

Angular 6 - Writing a Resolve class for routing that can return more than one dataset


I was reading online how to implement the resolve functionality with routes in Angular. However in every example I came across the resolve class that was written only took specific data from one service. e.g:

import { Injectable } from '@angular/core';
import { APIService } from './api.service';

import { Resolve } from '@angular/router';

@Injectable()
export class APIResolver implements Resolve<any> {
  constructor(private apiService: APIService) {}

  resolve() {
    return this.apiService.getItems();
  }

}

In app.routing.ts:

const routes: Routes = [
{
  path: 'items/:date',
  component: ItemsComponent,
  resolve: { items: APIResolver }
}
]

But what if I want multiple resolves? e.g:

import { Injectable } from '@angular/core';
import { APIService } from './api.service';

import { Resolve } from '@angular/router';

@Injectable()
export class APIResolver implements Resolve<any> {
  constructor(private apiService: APIService) {}

  resolveItems() {
    return this.apiService.getItems();
  }

 resolveCars() {
    return this.apiService.getCars();
  }

 resolvePeople() {
    return this.apiService.getPeople();
  }

}

How can I refactor these online examples so I can grab different resolve data?

I apologize if this question sounds a bit ambiguous. I can clarify if needed.


Solution

  • Unfortunately, this is not possible. If you want to share logic, you can extend base class like this:

    export abstract class APIResolve<T> implements Resolve<T> {
      constructor(readonly apiService: APIService) {}
    
      abstract resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T>;
    }
    

    and have multiple resolvers:

    export class APIItemResolve<T> extends APIResolve<T> {
      resolve(): Observable<T> {
        return this.apiService.getItems();
      }
    }
    
    export class APIPeopleResolve<T> extends APIResolve<T> {
      resolve(): Observable<T> {
        return this.apiService.getPeople();
      }
    }
    
    export class APICarResolve<T> extends APIResolve<T> {
      resolve(): Observable<T> {
        return this.apiService.getItems();
      }
    }
    

    and have your routes like this:

    const routes: Routes = [{
      path: 'items/:date',
      component: ItemsComponent,
      resolve: { 
        items: APIItemResolve,
        peoples: APIPeopleResolve,
        cars: APICarResolve
      }
    }]
    

    Another way is to make a global resolve, and have your items/peoples/cars saved in a shared Service instead of on the Route data