Resolver
Resolvers is used to provide data, before activating route, in brief, force the application to show the view only after loading the data. For easier understanding I will show it on the example.
Example of use:
I have a basic value model and I want to display it in the view.
export class Value { id: number; name: string; }
Service for retrieving value from API with passing id parameter in URL.
getValue() { this.valueService.getValue(+this.route.snapshot.params['id']).subscribe((value: Value) => { this.value = value; }); }
Simple view.
<strong class="text-center"> <p>Value:</p> <p>{{value.Name}}</p> <p>{{value.Id}}</p> </strong>
After redirect to http://localhost:4200/value/1, we get error in console.
But our view loaded correctly. This happens because as I mentioned earlier when rendering the view component value , there is no model to display yet. To fix the error, we can use “elvis” operators.
<strong class="text-center"> <p>Value:</p> <p>{{value?.Name}}</p> <p>{{value?.Id}}</p> </strong>
It solves our error, however it is not recommended to use it often.
So the resolvers come here for help.
To use the resolver, I need to write a service that implements the interface resolve. The resolve method can take two parameters, ActivatedRouteSnapshot and RouterStateSnapshot.
Example of the resolver implementation:
@Injectable() export class ValueResolver implements Resolve<string> { constructor(private valueService: ValueService, private router: Router) { } resolve(route: ActivatedRouteSnapshot): Observable<string> { return this.valueService.getValue(route.params['id']).pipe( catchError(error => { console.log('Error'); this.router.navigate(['/home']); return of(null); }) ); } }
Now I need to register it in app.module.ts in providers.
@NgModule({ ... providers: [ ValueResolver ], ... })
Then pass the resolver in routing.
const routes: Routes = [ ... { path: 'value/:id', component: ValueComponent, resolve: { value : ValueResolver } }, ... ];
The ActivatedRoute interface gives us access to the ActivatedRouteSnapshot snapshot. It has access to a data object that contains data received from (in our case) resolver.
Let’s use the fact that our resolver returns the object observer and subscribe to it.
ngOnInit() { this.route.data.subscribe(result => { this.value = result['value']; }); }
We refer to the ‘value’ properity because that’s how I set it up in routing.
After changing the view
<strong class="text-center"> <p>Value:</p> <p>{{value.Name}}</p> <p>{{value.Id}}</p> </strong>
everything loads correctly without any errors.
Code available on github.