Reputation: 117
I need an equivalent solution for the angular1.x $templateCache
:
On App start I have to translate and configure all html views depending on the user's profile, role, permissions, language and current location. I want to accomplish this on the server side with ASP.NET Razor syntax and tools in one request (not in one for each component). This request should place all ready to use templates into angular2 client side cache. From now on every component which references its template will be served from this cache first, if available. In Angular1.x it was easily possible to load all the template in one request, separated by <script id="myView.html" type="text/ng-template">...</script>
. Before placing them into the cache I had to compile each template by calling $compiler()
.
How can I accomplish this in Angular2?
One possible solution I could imagine would be if Angular2 supports Component's templateUrl
as a function()
. This way I could build my own cache.
Upvotes: 1
Views: 790
Reputation: 117
After some more research and digging into the angular2 source code this $templateCache in Angular 2? pointed me to the right solution. I have to register a new custom Http and a custom XHR implementation via provide():
providers: [HTTP_PROVIDERS,
provide(Http, {
useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions) => new HttpInterceptor(xhrBackend, requestOptions),
deps: [XHRBackend, RequestOptions]
}),
provide(XHR, {
useFactory: (http: Http) => new XHRInterceptor(http), deps: [Http]
})],
The XHRInterceptor (implementation of XHR interface) is injected and internally used by angular2 each time angular2 loads html temlates via Compontent's tempateUrl. Because we inject our custom Http implementation into XHRInterceptor constructor and delegate all get requests through HttpInterceptor we gain full control over all http requests from our application:
export class XHRInterceptor extends XHR {
constructor(private _http: Http) {
super()
}
get(url: string): Promise<string> {
var completer: PromiseCompleter<string> = PromiseWrapper.completer();
this._http.get(url).map(data=> {
return data.text();
}).subscribe( data => {
completer.resolve(data);
}, error=>{
completer.reject(`Failed to load ${url}`, null);
});
return completer.promise;
}
}
and this is my HttpInterceptor class:
export class HttpInterceptor extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
if (typeof url === "string") {
return this.interceptResult(super.request(this.interceptUrl(url), this.interceptOptions(options)));
} else {
return this.interceptResult(super.request(url, this.interceptOptions(options)));
}
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.interceptResult(super.get(this.interceptUrl(url), this.interceptOptions(options)));
}
post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.interceptResult(super.post(this.interceptUrl(url), body, this.interceptOptions(options)));
}
put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.interceptResult(super.put(this.interceptUrl(url), body, this.interceptOptions(options)));
}
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.interceptResult(super.delete(this.interceptUrl(url), this.interceptOptions(options)));
}
interceptUrl(url: string): string {
// Do some stuff with the url....
//...
return url;
}
interceptOptions(options?: RequestOptionsArgs): RequestOptionsArgs {
// prepare options...
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
// insert some custom headers...
// options.headers.append('Content-Type', 'application/json');
return options;
}
interceptResult(observable: Observable<Response>): Observable<Response> {
// Do some stuff with the result...
// ...
return observable;
}
}
Upvotes: 1