This example will show you how you can resolve data fetched from a service before rendering your application's view.
Uses angular/router 3.0.0-beta.2 at the time of writing
users.service.ts
... import { Http, Response } from '@angular/http'; import { Observable } from 'rxjs/Rx'; import { User } from './user.ts'; @Injectable() export class UsersService { constructor(public http:Http) {} /** * Returns all users * @returns {Observable<User[]>} */ index():Observable<User[]> { return this.http.get('http://mywebsite.com/api/v1/users') .map((res:Response) => res.json()); } /** * Returns a user by ID * @param id * @returns {Observable<User>} */ get(id:number|string):Observable<User> { return this.http.get('http://mywebsite.com/api/v1/users/' + id) .map((res:Response) => res.json()); } }
users.resolver.ts
... import { UsersService } from './users.service.ts'; import { Observable } from 'rxjs/Rx'; import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router"; @Injectable() export class UsersResolver implements Resolve<User[] | User> { // Inject UsersService into the resolver constructor(private service:UsersService) {} resolve(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<User[] | User> { // If userId param exists in current URL, return a single user, else return all users // Uses brackets notation to access `id` to suppress editor warning, may use dot notation if you create an interface extending ActivatedRoute with an optional id? attribute if (route.params['id']) return this.service.get(route.params['id']); return this.service.index(); } }
users.component.ts
This is a page component with a list of all users. It will work similarly for User detail page component, replace data.users
with data.user
or whatever key defined in app.routes.ts(see below)
... import { ActivatedRoute} from "@angular/router"; @Component(...) export class UsersComponent { users:User[]; constructor(route: ActivatedRoute) { route.data.subscribe(data => { // data['Match key defined in RouterConfig, see below'] this.users = data.users; }); } /** * It is not required to unsubscribe from the resolver as Angular's HTTP * automatically completes the subscription when data is received from the server */ }
app.routes.ts
... import { UsersResolver } from './resolvers/users.resolver'; export const routes:RouterConfig = <RouterConfig>[ ... { path: 'user/:id', component: UserComponent, resolve: { // hence data.user in UserComponent user: UsersResolver } }, { path: 'users', component: UsersComponent, resolve: { // hence data.users in UsersComponent, note the pluralisation users: UsersResolver } }, ... ] ...
app.resolver.ts
Optionally bundle multiple resolvers together.
IMPORTANT: Services used in resolver must be imported first or you will get a 'No provider for ..Resolver error'. Remember that these services will be available globally and you will not need to declare them in any component's providers
anymore. Be sure to unsubscribe from any subscription to prevent memory leak
... import { UsersService } from './users.service'; import { UsersResolver } from './users.resolver'; export const ROUTE_RESOLVERS = [ ..., UsersService, UsersResolver ]
main.browser.ts
Resolvers have to be injected during bootstrapping.
... import {bootstrap} from '@angular/platform-browser-dynamic'; import { ROUTE_RESOLVERS } from './app.resolver'; bootstrap(<Type>App, [ ... ...ROUTE_RESOLVERS ]) .catch(err => console.error(err));