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));