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