Load data before loading Component in Angular
In some scenarios, you might want to load some data from an API or async call before you render your component. We can make use of the Angular resolver feature provided in Angular Router to achieve that.
In this Angular tutorial, we will use the route resolver to load some data and inject it into the component before rendering it.
Without saying a thing further let’s just start the implementation.
Note. We are using Angular 8 for this tutorial.
Setup
Start a new angular app …
Once the app is created let’s create a new component and also add routing.
This will generate a component named dashboard for us and the second command will add the routing module.
Now, let’s add our routes.
import { CommonModule } from '@angular/common';
import { Routes, RouterModule } from '@angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent
},
{
path: '',
redirectTo: 'dashboard',
pathMatch: 'full'
}
]
@NgModule({
declarations: [],
imports: [
CommonModule,
RouterModule.forRoot(routes)
],
exports: [RouterModule]
})
export class AppRoutingModule { }
Finishing the basic setup by adding the AppRoutingModule to the imports of the main App Module and placing router-outlet in app.component.html
..
imports: [
...,
AppRoutingModule,
...,
],
..
...
<div style="text-align:center">
<h1>
Welcome to resolve tutorial!
</h1>
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<h2>Load Route ...</h2>
<router-outlet></router-outlet>
Run ng serve to see if everything is in place.
Using Resolve to Inject data
Now let’s create a service that would return us data asynchronously. We will use setTimeout function to simulate an asynchronous call to an API server.
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService {
user = {
name: 'Mason',
age: 19,
profession: 'Footballer'
}
constructor() { }
getData(): Observable<any>{
return new Observable((o)=>{
setTimeout(()=>{
o.next(this.user);
}, 1000)
})
}
}
Next, we will create a Data Resolver service which implements the interface Resolve.
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { take, map } from 'rxjs/operators';
import { DataService } from './data.service';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataResolverService implements Resolve <Observable<any>>{
constructor(private ds: DataService) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){
return this.ds.getData().pipe(
take(1),
map(userdata => userdata)
)
}
}
This Resolver can be added to the route as shown below.
{
path: 'dashboard',
component: DashboardComponent,
resolve: {
userdata: DataResolverService
}
},
{
path: '',
redirectTo: 'dashboard',
pathMatch: 'full'
}
]
The key userdata which can be anything is important here as in our Dashboard component we will use the same key to access the resolved User’s Data. Let’s see that below…
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
userdata: any;
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.userdata = this.route.snapshot.data.userdata; // get data from resolver
}
}
Now the user data should be available before the component instantiates.

2
Multiple Resolvers in Angular
Angular routers support multiple resolvers.
path: 'dashboard',
component: DashboardComponent,
resolve: {
userdata: DataResolverService,
bar: Resolver2,
// more resolves here...
}
}
These resolvers resolve in parallel independent of each other. In the case where there are more than one Resolvers, Angular will load the component only when all of the Resolvers are resolved.
How to pass data from one resolve to another in Angular?
One of the common problems you might come up with is passing the data from 1st resolve to the next. As of at the time of writing this article, the feature is not yet supported by the Angular Router. There is an active feature PR running for that.
To get around this what you can do is, create a wrapper service which will pull all the data one after another and then pass that to resolve.
Code
You can find an example application that uses resolve on this link.
Conclusion
So we have seen how resolve can be of great use to prefetch data before loading the component in Angular. This is the right way to load any dependent data without which your component cannot load.
Keep Learning…
1 comment
Leave a Comment
Great tuto, thanks