|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
import {Injectable} from 'angular2/di';
|
|
|
|
|
import {isBlank, isPresent, BaseException, stringify} from 'angular2/src/facade/lang';
|
|
|
|
|
import {Map, MapWrapper, StringMapWrapper, StringMap} from 'angular2/src/facade/collection';
|
|
|
|
|
import {Map, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
|
|
|
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
|
|
|
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
|
|
|
|
|
|
|
|
@ -15,35 +15,62 @@ import {UrlResolver} from 'angular2/src/services/url_resolver';
|
|
|
|
|
*/
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class TemplateLoader {
|
|
|
|
|
_htmlCache: StringMap<string, /*element*/ any> = StringMapWrapper.create();
|
|
|
|
|
_cache: Map<string, Promise<string>> = MapWrapper.create();
|
|
|
|
|
|
|
|
|
|
constructor(public _xhr: XHR, urlResolver: UrlResolver) {}
|
|
|
|
|
constructor(private _xhr: XHR, urlResolver: UrlResolver) {}
|
|
|
|
|
|
|
|
|
|
load(template: ViewDefinition): Promise</*element*/ any> {
|
|
|
|
|
if (isPresent(template.template)) {
|
|
|
|
|
return PromiseWrapper.resolve(DOM.createTemplate(template.template));
|
|
|
|
|
}
|
|
|
|
|
var url = template.absUrl;
|
|
|
|
|
if (isPresent(url)) {
|
|
|
|
|
var promise = StringMapWrapper.get(this._htmlCache, url);
|
|
|
|
|
load(view: ViewDefinition): Promise</*element*/ any> {
|
|
|
|
|
let html;
|
|
|
|
|
let fetchedStyles;
|
|
|
|
|
|
|
|
|
|
if (isBlank(promise)) {
|
|
|
|
|
// TODO(vicb): change error when TS gets fixed
|
|
|
|
|
// https://github.com/angular/angular/issues/2280
|
|
|
|
|
// throw new BaseException(`Failed to fetch url "${url}"`);
|
|
|
|
|
promise = PromiseWrapper.then(this._xhr.get(url), html => {
|
|
|
|
|
var template = DOM.createTemplate(html);
|
|
|
|
|
return template;
|
|
|
|
|
}, _ => PromiseWrapper.reject(new BaseException(`Failed to fetch url "${url}"`), null));
|
|
|
|
|
|
|
|
|
|
StringMapWrapper.set(this._htmlCache, url, promise);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We need to clone the result as others might change it
|
|
|
|
|
// (e.g. the compiler).
|
|
|
|
|
return promise.then((tplElement) => DOM.clone(tplElement));
|
|
|
|
|
// Load the HTML
|
|
|
|
|
if (isPresent(view.template)) {
|
|
|
|
|
html = PromiseWrapper.resolve(view.template);
|
|
|
|
|
} else if (isPresent(view.templateAbsUrl)) {
|
|
|
|
|
html = this._loadText(view.templateAbsUrl);
|
|
|
|
|
} else {
|
|
|
|
|
throw new BaseException('View should have either the templateUrl or template property set');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new BaseException('View should have either the url or template property set');
|
|
|
|
|
// Load the styles
|
|
|
|
|
if (isPresent(view.styleAbsUrls) && view.styleAbsUrls.length > 0) {
|
|
|
|
|
fetchedStyles = ListWrapper.map(view.styleAbsUrls, url => this._loadText(url));
|
|
|
|
|
} else {
|
|
|
|
|
fetchedStyles = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Inline the styles and return a template element
|
|
|
|
|
return PromiseWrapper.all(ListWrapper.concat([html], fetchedStyles))
|
|
|
|
|
.then((res: List<string>) => {
|
|
|
|
|
let html = res[0];
|
|
|
|
|
let fetchedStyles = ListWrapper.slice(res, 1);
|
|
|
|
|
|
|
|
|
|
html = _createStyleTags(view.styles) + _createStyleTags(fetchedStyles) + html;
|
|
|
|
|
|
|
|
|
|
return DOM.createTemplate(html);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _loadText(url: string): Promise<string> {
|
|
|
|
|
var response = MapWrapper.get(this._cache, url);
|
|
|
|
|
|
|
|
|
|
if (isBlank(response)) {
|
|
|
|
|
// TODO(vicb): change error when TS gets fixed
|
|
|
|
|
// https://github.com/angular/angular/issues/2280
|
|
|
|
|
// throw new BaseException(`Failed to fetch url "${url}"`);
|
|
|
|
|
response = PromiseWrapper.catchError(
|
|
|
|
|
this._xhr.get(url),
|
|
|
|
|
_ => PromiseWrapper.reject(new BaseException(`Failed to fetch url "${url}"`), null));
|
|
|
|
|
|
|
|
|
|
MapWrapper.set(this._cache, url, response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _createStyleTags(styles?: List<string>): string {
|
|
|
|
|
return isBlank(styles) ?
|
|
|
|
|
'' :
|
|
|
|
|
ListWrapper.map(styles, css => `<style type='text/css'>${css}</style>`).join('');
|
|
|
|
|
}
|
|
|
|
|