I understand this question has been around for a while. This is how we found a workaround in LastCall.cc using a resolver (not very performant though)
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import {
Resolve,
RouterStateSnapshot,
ActivatedRouteSnapshot
} from '@angular/router';
import { makeStateKey, TransferState } from '@angular/platform-browser';
import { SearchService } from '@app/services/search.service';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
@Injectable()
export class ProductDetailsResolver implements Resolve<any> {
private result: any;
constructor(
private readonly state: TransferState,
private search: SearchService
) { }
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> {
const id = route.paramMap.get('dealId');
const RESULT_KEY = makeStateKey<any>('product-details-resolver.result' + id);
if (this.state.hasKey(RESULT_KEY)) {
const res = of(this.state.get<any>(RESULT_KEY, null));
this.state.remove(RESULT_KEY);
return res;
} else {
this.state.onSerialize(RESULT_KEY, () => this.result);
return this.search.searchDealById(id)
.do(result => {
this.result = result;
}).catch((error) => {
console.log('API Error --> ', error);
this.result = {};
return Observable.of({});
});
}
}
}
The service above can be any async data fetcher as long as it returns an Observable
The StateTransfer handshake will force the resolver to wait for API results. The catch is, there is no timeout and if your API has any issues, it will seem as if it's hanging for the end-user.
Here is how you implement the route with resolver:
path: 'campaigns',
children: [
{
path: ':dealId',
component: EcommerceProductDetails,
resolve: { result: ProductDetailsResolver },
runGuardsAndResolvers: 'paramsOrQueryParamsChange'
}
]
and here is how to get the data in the component:
ngOnInit() {
this.route.data.subscribe(data => {
this.deal = <IDeal>data.result._source;
});
}
ngOnInit()method? To be sure the component is able to load and the data is present you could use a resolver instead, this way you can be sure the data is available in the component: angular.io/api/router/Resolve - Denisasync ngOnInit() { this.message = 'Hello!!'; var data = await this.http.get('https://api.github.com/users/github').toPromise(); this.message = data['bio']; }and it doesn't wait. It shows initial message and then make XHR call. What was the point of Angular Universal then - Toolkit