Angular Route Resolve - The easy way

Resolving async callbacks was easy to implement in AngularJS. However in Angular this seems to be slightly complex. As per documentation you need to implement a class of the type Resolve. This interface requires you to implement a method with following signature.

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T>|Promise<T>|T

My opinion is that its tedious to create one class per item we need to resolve. The current application that I am working on require 7 to 8 different HTTP calls (depending on context) to be resolved during app startup. An alternate approach is described below, which uses a static method of the same signature as above.

Create a shared class that will hold methods that has the same signature of the interface. Each of these methods act as individual resolvers. These methods should be static methods so that we can refer to them later on without instantiating the class. Hence we need to do a workaround to inject http object.


/shared/crud.service.ts

@Injectable()
export class CrudService {

  private static http: HttpClient;
  private static serverUrl = 'https://example.com';

  constructor(private httpClient: HttpClient) {
    CrudService.http = this.httpClient;
  }

  static User(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){
    let url = CrudService.serverUrl + '/api/user';
    return CrudService.http.get(url);
  }
  static Item(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){
    let url = CrudService.serverUrl + '/api/item';
    return CrudService.http.get(url);
  }
}


In the routing module of the component where we need the resolves, add to the providers of the NgModule, the static methods created in CrudService and give them names. These names can be used in the resolve option in the Routes deceleration.

/app/dashboard.routing.ts

const dashboardRoutes: Routes = [

  {

    path: 'Dashboard',

    component: DashboardComponent,

    resolve: {

      users: 'User',
      items: 'Item'
    }
  }
];

@NgModule({
  imports: [
    RouterModule.forChild(dashboardRoutes)
  ],
  declarations: [],
  exports: [
    RouterModule
  ],
  providers: [
    { provide: 'User', useValue: CrudService.User },
    { provide: 'Item', useValue: CrudService.Item }
  ]
})
export class DashboardRouteModule {

}

In the component where we need the resolved values, inject ActivatedRoute and fetch the value from the snapshot of route, like below.

/app/dashbaord.component.ts

@Component(...)
export class DashboardComponent implements OnInit {

  users: any;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.users = this.route.snapshot.data.users;
  }
}

Comments

Post a Comment