@ -49,6 +49,16 @@ export class View {
|
|||||||
*/
|
*/
|
||||||
template: string;
|
template: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies stylesheet URLs for an angular component.
|
||||||
|
*/
|
||||||
|
styleUrls: List<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an inline stylesheet for an angular component.
|
||||||
|
*/
|
||||||
|
styles: List<string>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies a list of directives that can be used within a template.
|
* Specifies a list of directives that can be used within a template.
|
||||||
*
|
*
|
||||||
@ -78,13 +88,16 @@ export class View {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a custom renderer for this View.
|
* Specify a custom renderer for this View.
|
||||||
* If this is set, neither `template`, `templateURL` nor `directives` are used.
|
* If this is set, neither `template`, `templateUrl`, `styles`, `styleUrls` nor `directives` are
|
||||||
|
* used.
|
||||||
*/
|
*/
|
||||||
renderer: string;
|
renderer: string;
|
||||||
|
|
||||||
constructor({templateUrl, template, directives, renderer}: ViewArgs = {}) {
|
constructor({templateUrl, template, directives, renderer, styles, styleUrls}: ViewArgs = {}) {
|
||||||
this.templateUrl = templateUrl;
|
this.templateUrl = templateUrl;
|
||||||
this.template = template;
|
this.template = template;
|
||||||
|
this.styleUrls = styleUrls;
|
||||||
|
this.styles = styles;
|
||||||
this.directives = directives;
|
this.directives = directives;
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
}
|
}
|
||||||
@ -94,4 +107,6 @@ export interface ViewArgs {
|
|||||||
template?: string;
|
template?: string;
|
||||||
directives?: List<Type | any | List<any>>;
|
directives?: List<Type | any | List<any>>;
|
||||||
renderer?: string;
|
renderer?: string;
|
||||||
|
styles?: List<string>;
|
||||||
|
styleUrls?: List<string>;
|
||||||
}
|
}
|
||||||
|
@ -205,6 +205,7 @@ export class Compiler {
|
|||||||
var componentUrl =
|
var componentUrl =
|
||||||
this._urlResolver.resolve(this._appUrl, this._componentUrlMapper.getUrl(component));
|
this._urlResolver.resolve(this._appUrl, this._componentUrlMapper.getUrl(component));
|
||||||
var templateAbsUrl = null;
|
var templateAbsUrl = null;
|
||||||
|
var styleAbsUrls = null;
|
||||||
if (isPresent(view.templateUrl)) {
|
if (isPresent(view.templateUrl)) {
|
||||||
templateAbsUrl = this._urlResolver.resolve(componentUrl, view.templateUrl);
|
templateAbsUrl = this._urlResolver.resolve(componentUrl, view.templateUrl);
|
||||||
} else if (isPresent(view.template)) {
|
} else if (isPresent(view.template)) {
|
||||||
@ -213,9 +214,15 @@ export class Compiler {
|
|||||||
// is able to resolve urls in stylesheets.
|
// is able to resolve urls in stylesheets.
|
||||||
templateAbsUrl = componentUrl;
|
templateAbsUrl = componentUrl;
|
||||||
}
|
}
|
||||||
|
if (isPresent(view.styleUrls)) {
|
||||||
|
styleAbsUrls =
|
||||||
|
ListWrapper.map(view.styleUrls, url => this._urlResolver.resolve(componentUrl, url));
|
||||||
|
}
|
||||||
return new renderApi.ViewDefinition({
|
return new renderApi.ViewDefinition({
|
||||||
componentId: stringify(component),
|
componentId: stringify(component),
|
||||||
absUrl: templateAbsUrl, template: view.template,
|
templateAbsUrl: templateAbsUrl, template: view.template,
|
||||||
|
styleAbsUrls: styleAbsUrls,
|
||||||
|
styles: view.styles,
|
||||||
directives: ListWrapper.map(directives, directiveBinding => directiveBinding.metadata)
|
directives: ListWrapper.map(directives, directiveBinding => directiveBinding.metadata)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -256,19 +256,25 @@ export class RenderViewRef {}
|
|||||||
|
|
||||||
export class ViewDefinition {
|
export class ViewDefinition {
|
||||||
componentId: string;
|
componentId: string;
|
||||||
absUrl: string;
|
templateAbsUrl: string;
|
||||||
template: string;
|
template: string;
|
||||||
directives: List<DirectiveMetadata>;
|
directives: List<DirectiveMetadata>;
|
||||||
|
styleAbsUrls: List<string>;
|
||||||
|
styles: List<string>;
|
||||||
|
|
||||||
constructor({componentId, absUrl, template, directives}: {
|
constructor({componentId, templateAbsUrl, template, styleAbsUrls, styles, directives}: {
|
||||||
componentId?: string,
|
componentId?: string,
|
||||||
absUrl?: string,
|
templateAbsUrl?: string,
|
||||||
template?: string,
|
template?: string,
|
||||||
|
styleAbsUrls?: List<string>,
|
||||||
|
styles?: List<string>,
|
||||||
directives?: List<DirectiveMetadata>
|
directives?: List<DirectiveMetadata>
|
||||||
}) {
|
}) {
|
||||||
this.componentId = componentId;
|
this.componentId = componentId;
|
||||||
this.absUrl = absUrl;
|
this.templateAbsUrl = templateAbsUrl;
|
||||||
this.template = template;
|
this.template = template;
|
||||||
|
this.styleAbsUrls = styleAbsUrls;
|
||||||
|
this.styles = styles;
|
||||||
this.directives = directives;
|
this.directives = directives;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,9 @@ export class DomCompiler extends RenderCompiler {
|
|||||||
compileHost(directiveMetadata: DirectiveMetadata): Promise<ProtoViewDto> {
|
compileHost(directiveMetadata: DirectiveMetadata): Promise<ProtoViewDto> {
|
||||||
var hostViewDef = new ViewDefinition({
|
var hostViewDef = new ViewDefinition({
|
||||||
componentId: directiveMetadata.id,
|
componentId: directiveMetadata.id,
|
||||||
absUrl: null, template: null,
|
templateAbsUrl: null, template: null,
|
||||||
|
styles: null,
|
||||||
|
styleAbsUrls: null,
|
||||||
directives: [directiveMetadata]
|
directives: [directiveMetadata]
|
||||||
});
|
});
|
||||||
var element = DOM.createElement(directiveMetadata.selector);
|
var element = DOM.createElement(directiveMetadata.selector);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {Injectable} from 'angular2/di';
|
import {Injectable} from 'angular2/di';
|
||||||
import {isBlank, isPresent, BaseException, stringify} from 'angular2/src/facade/lang';
|
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 {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
|
||||||
@ -15,35 +15,62 @@ import {UrlResolver} from 'angular2/src/services/url_resolver';
|
|||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TemplateLoader {
|
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> {
|
load(view: ViewDefinition): Promise</*element*/ any> {
|
||||||
if (isPresent(template.template)) {
|
let html;
|
||||||
return PromiseWrapper.resolve(DOM.createTemplate(template.template));
|
let fetchedStyles;
|
||||||
|
|
||||||
|
// 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');
|
||||||
}
|
}
|
||||||
var url = template.absUrl;
|
|
||||||
if (isPresent(url)) {
|
|
||||||
var promise = StringMapWrapper.get(this._htmlCache, url);
|
|
||||||
|
|
||||||
if (isBlank(promise)) {
|
// 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
|
// TODO(vicb): change error when TS gets fixed
|
||||||
// https://github.com/angular/angular/issues/2280
|
// https://github.com/angular/angular/issues/2280
|
||||||
// throw new BaseException(`Failed to fetch url "${url}"`);
|
// throw new BaseException(`Failed to fetch url "${url}"`);
|
||||||
promise = PromiseWrapper.then(this._xhr.get(url), html => {
|
response = PromiseWrapper.catchError(
|
||||||
var template = DOM.createTemplate(html);
|
this._xhr.get(url),
|
||||||
return template;
|
_ => PromiseWrapper.reject(new BaseException(`Failed to fetch url "${url}"`), null));
|
||||||
}, _ => PromiseWrapper.reject(new BaseException(`Failed to fetch url "${url}"`), null));
|
|
||||||
|
|
||||||
StringMapWrapper.set(this._htmlCache, url, promise);
|
MapWrapper.set(this._cache, url, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to clone the result as others might change it
|
return response;
|
||||||
// (e.g. the compiler).
|
|
||||||
return promise.then((tplElement) => DOM.clone(tplElement));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new BaseException('View should have either the url or template property set');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _createStyleTags(styles?: List<string>): string {
|
||||||
|
return isBlank(styles) ?
|
||||||
|
'' :
|
||||||
|
ListWrapper.map(styles, css => `<style type='text/css'>${css}</style>`).join('');
|
||||||
|
}
|
||||||
|
@ -29,7 +29,7 @@ export class ShadowDomCompileStep implements CompileStep {
|
|||||||
|
|
||||||
_processStyleElement(current: CompileElement, control: CompileControl) {
|
_processStyleElement(current: CompileElement, control: CompileControl) {
|
||||||
var stylePromise = this._shadowDomStrategy.processStyleElement(
|
var stylePromise = this._shadowDomStrategy.processStyleElement(
|
||||||
this._template.componentId, this._template.absUrl, current.element);
|
this._template.componentId, this._template.templateAbsUrl, current.element);
|
||||||
if (isPresent(stylePromise) && PromiseWrapper.isPromise(stylePromise)) {
|
if (isPresent(stylePromise) && PromiseWrapper.isPromise(stylePromise)) {
|
||||||
ListWrapper.push(this._subTaskPromises, stylePromise);
|
ListWrapper.push(this._subTaskPromises, stylePromise);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import {NG_BINDING_CLASS} from '../util';
|
|||||||
|
|
||||||
import {RenderProtoViewRef} from '../../api';
|
import {RenderProtoViewRef} from '../../api';
|
||||||
|
|
||||||
export function resolveInternalDomProtoView(protoViewRef: RenderProtoViewRef) {
|
export function resolveInternalDomProtoView(protoViewRef: RenderProtoViewRef): DomProtoView {
|
||||||
return (<DomProtoViewRef>protoViewRef)._protoView;
|
return (<DomProtoViewRef>protoViewRef)._protoView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class _TemplateExtractor {
|
|||||||
|
|
||||||
Future<_ExtractResult> extractTemplates(ViewDefinition viewDef) async {
|
Future<_ExtractResult> extractTemplates(ViewDefinition viewDef) async {
|
||||||
// Check for "imperative views".
|
// Check for "imperative views".
|
||||||
if (viewDef.template == null && viewDef.absUrl == null) return null;
|
if (viewDef.template == null && viewDef.templateAbsUrl == null) return null;
|
||||||
|
|
||||||
var templateEl = await _loader.load(viewDef);
|
var templateEl = await _loader.load(viewDef);
|
||||||
|
|
||||||
|
@ -210,11 +210,11 @@ class _TemplateExtractVisitor extends Object with RecursiveAstVisitor<Object> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (keyString == 'templateUrl') {
|
if (keyString == 'templateUrl') {
|
||||||
if (viewDef.absUrl != null) {
|
if (viewDef.templateAbsUrl != null) {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Found multiple values for "templateUrl". Source: ${node}');
|
'Found multiple values for "templateUrl". Source: ${node}');
|
||||||
}
|
}
|
||||||
viewDef.absUrl = valueString;
|
viewDef.templateAbsUrl = valueString;
|
||||||
} else {
|
} else {
|
||||||
// keyString == 'template'
|
// keyString == 'template'
|
||||||
if (viewDef.template != null) {
|
if (viewDef.template != null) {
|
||||||
|
@ -100,30 +100,45 @@ export function main() {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should fill absUrl given inline templates', inject([AsyncTestCompleter], (async) => {
|
it('should fill templateAbsUrl given inline templates',
|
||||||
|
inject([AsyncTestCompleter], (async) => {
|
||||||
cmpUrlMapper.setComponentUrl(MainComponent, '/mainComponent');
|
cmpUrlMapper.setComponentUrl(MainComponent, '/mainComponent');
|
||||||
captureTemplate(new viewAnn.View({template: '<div></div>'}))
|
captureTemplate(new viewAnn.View({template: '<div></div>'}))
|
||||||
.then((renderTpl) => {
|
.then((renderTpl) => {
|
||||||
expect(renderTpl.absUrl).toEqual('http://www.app.com/mainComponent');
|
expect(renderTpl.templateAbsUrl).toEqual('http://www.app.com/mainComponent');
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not fill absUrl given no inline template or template url',
|
it('should not fill templateAbsUrl given no inline template or template url',
|
||||||
inject([AsyncTestCompleter], (async) => {
|
inject([AsyncTestCompleter], (async) => {
|
||||||
cmpUrlMapper.setComponentUrl(MainComponent, '/mainComponent');
|
cmpUrlMapper.setComponentUrl(MainComponent, '/mainComponent');
|
||||||
captureTemplate(new viewAnn.View({template: null, templateUrl: null}))
|
captureTemplate(new viewAnn.View({template: null, templateUrl: null}))
|
||||||
.then((renderTpl) => {
|
.then((renderTpl) => {
|
||||||
expect(renderTpl.absUrl).toBe(null);
|
expect(renderTpl.templateAbsUrl).toBe(null);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should fill absUrl given url template', inject([AsyncTestCompleter], (async) => {
|
it('should fill templateAbsUrl given url template', inject([AsyncTestCompleter], (async) => {
|
||||||
cmpUrlMapper.setComponentUrl(MainComponent, '/mainComponent');
|
cmpUrlMapper.setComponentUrl(MainComponent, '/mainComponent');
|
||||||
captureTemplate(new viewAnn.View({templateUrl: '/someTemplate'}))
|
captureTemplate(new viewAnn.View({templateUrl: '/someTemplate'}))
|
||||||
.then((renderTpl) => {
|
.then((renderTpl) => {
|
||||||
expect(renderTpl.absUrl).toEqual('http://www.app.com/mainComponent/someTemplate');
|
expect(renderTpl.templateAbsUrl)
|
||||||
|
.toEqual('http://www.app.com/mainComponent/someTemplate');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should fill styleAbsUrls given styleUrls', inject([AsyncTestCompleter], (async) => {
|
||||||
|
cmpUrlMapper.setComponentUrl(MainComponent, '/mainComponent');
|
||||||
|
captureTemplate(new viewAnn.View({styleUrls: ['/1.css', '/2.css']}))
|
||||||
|
.then((renderTpl) => {
|
||||||
|
expect(renderTpl.styleAbsUrls)
|
||||||
|
.toEqual([
|
||||||
|
'http://www.app.com/mainComponent/1.css',
|
||||||
|
'http://www.app.com/mainComponent/2.css'
|
||||||
|
]);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
|
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {List, ListWrapper, Map, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, Map, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Type, isBlank, stringify, isPresent} from 'angular2/src/facade/lang';
|
import {Type, isBlank, stringify, isPresent, BaseException} from 'angular2/src/facade/lang';
|
||||||
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
import {DomCompiler} from 'angular2/src/render/dom/compiler/compiler';
|
import {DomCompiler} from 'angular2/src/render/dom/compiler/compiler';
|
||||||
@ -90,7 +90,7 @@ export function runCompilerCommonTests() {
|
|||||||
it('should load url templates', inject([AsyncTestCompleter], (async) => {
|
it('should load url templates', inject([AsyncTestCompleter], (async) => {
|
||||||
var urlData = MapWrapper.createFromStringMap({'someUrl': 'url component'});
|
var urlData = MapWrapper.createFromStringMap({'someUrl': 'url component'});
|
||||||
var compiler = createCompiler(EMPTY_STEP, urlData);
|
var compiler = createCompiler(EMPTY_STEP, urlData);
|
||||||
compiler.compile(new ViewDefinition({componentId: 'someId', absUrl: 'someUrl'}))
|
compiler.compile(new ViewDefinition({componentId: 'someId', templateAbsUrl: 'someUrl'}))
|
||||||
.then((protoView) => {
|
.then((protoView) => {
|
||||||
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element))
|
expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).element))
|
||||||
.toEqual('url component');
|
.toEqual('url component');
|
||||||
@ -101,7 +101,8 @@ export function runCompilerCommonTests() {
|
|||||||
it('should report loading errors', inject([AsyncTestCompleter], (async) => {
|
it('should report loading errors', inject([AsyncTestCompleter], (async) => {
|
||||||
var compiler = createCompiler(EMPTY_STEP, MapWrapper.create());
|
var compiler = createCompiler(EMPTY_STEP, MapWrapper.create());
|
||||||
PromiseWrapper.catchError(
|
PromiseWrapper.catchError(
|
||||||
compiler.compile(new ViewDefinition({componentId: 'someId', absUrl: 'someUrl'})),
|
compiler.compile(
|
||||||
|
new ViewDefinition({componentId: 'someId', templateAbsUrl: 'someUrl'})),
|
||||||
(e) => {
|
(e) => {
|
||||||
expect(e.message).toEqual(
|
expect(e.message).toEqual(
|
||||||
'Failed to load the template for "someId" : Failed to fetch url "someUrl"');
|
'Failed to load the template for "someId" : Failed to fetch url "someUrl"');
|
||||||
@ -207,14 +208,14 @@ class FakeTemplateLoader extends TemplateLoader {
|
|||||||
return PromiseWrapper.resolve(DOM.createTemplate(template.template));
|
return PromiseWrapper.resolve(DOM.createTemplate(template.template));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPresent(template.absUrl)) {
|
if (isPresent(template.templateAbsUrl)) {
|
||||||
var content = MapWrapper.get(this._urlData, template.absUrl);
|
var content = MapWrapper.get(this._urlData, template.templateAbsUrl);
|
||||||
return isPresent(content) ?
|
return isPresent(content) ?
|
||||||
PromiseWrapper.resolve(DOM.createTemplate(content)) :
|
PromiseWrapper.resolve(DOM.createTemplate(content)) :
|
||||||
PromiseWrapper.reject(`Failed to fetch url "${template.absUrl}"`, null);
|
PromiseWrapper.reject(`Failed to fetch url "${template.templateAbsUrl}"`, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PromiseWrapper.reject('Load failed', null);
|
throw new BaseException('View should have either the templateUrl or template property set');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ export function main() {
|
|||||||
loader = new TemplateLoader(xhr, new FakeUrlResolver());
|
loader = new TemplateLoader(xhr, new FakeUrlResolver());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('html', () => {
|
||||||
it('should load inline templates', inject([AsyncTestCompleter], (async) => {
|
it('should load inline templates', inject([AsyncTestCompleter], (async) => {
|
||||||
var template = new ViewDefinition({template: 'template template'});
|
var template = new ViewDefinition({template: 'template template'});
|
||||||
loader.load(template).then((el) => {
|
loader.load(template).then((el) => {
|
||||||
@ -36,8 +37,8 @@ export function main() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should load templates through XHR', inject([AsyncTestCompleter], (async) => {
|
it('should load templates through XHR', inject([AsyncTestCompleter], (async) => {
|
||||||
xhr.expect('base/foo', 'xhr template');
|
xhr.expect('base/foo.html', 'xhr template');
|
||||||
var template = new ViewDefinition({absUrl: 'base/foo'});
|
var template = new ViewDefinition({templateAbsUrl: 'base/foo.html'});
|
||||||
loader.load(template).then((el) => {
|
loader.load(template).then((el) => {
|
||||||
expect(DOM.content(el)).toHaveText('xhr template');
|
expect(DOM.content(el)).toHaveText('xhr template');
|
||||||
async.done();
|
async.done();
|
||||||
@ -45,12 +46,12 @@ export function main() {
|
|||||||
xhr.flush();
|
xhr.flush();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should cache template loaded through XHR but clone it as the compiler might change it',
|
it('should return a new template element on each call',
|
||||||
inject([AsyncTestCompleter], (async) => {
|
inject([AsyncTestCompleter], (async) => {
|
||||||
var firstEl;
|
var firstEl;
|
||||||
// we have only one xhr.expect, so there can only be one xhr call!
|
// we have only one xhr.expect, so there can only be one xhr call!
|
||||||
xhr.expect('base/foo', 'xhr template');
|
xhr.expect('base/foo.html', 'xhr template');
|
||||||
var template = new ViewDefinition({absUrl: 'base/foo'});
|
var template = new ViewDefinition({templateAbsUrl: 'base/foo.html'});
|
||||||
loader.load(template)
|
loader.load(template)
|
||||||
.then((el) => {
|
.then((el) => {
|
||||||
expect(DOM.content(el)).toHaveText('xhr template');
|
expect(DOM.content(el)).toHaveText('xhr template');
|
||||||
@ -66,23 +67,67 @@ export function main() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should throw when no template is defined', () => {
|
it('should throw when no template is defined', () => {
|
||||||
var template = new ViewDefinition({template: null, absUrl: null});
|
var template = new ViewDefinition({template: null, templateAbsUrl: null});
|
||||||
expect(() => loader.load(template))
|
expect(() => loader.load(template))
|
||||||
.toThrowError('View should have either the url or template property set');
|
.toThrowError('View should have either the templateUrl or template property set');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a rejected Promise when xhr loading fails',
|
it('should return a rejected Promise when XHR loading fails',
|
||||||
inject([AsyncTestCompleter], (async) => {
|
inject([AsyncTestCompleter], (async) => {
|
||||||
xhr.expect('base/foo', null);
|
xhr.expect('base/foo.html', null);
|
||||||
var template = new ViewDefinition({absUrl: 'base/foo'});
|
var template = new ViewDefinition({templateAbsUrl: 'base/foo.html'});
|
||||||
PromiseWrapper.then(loader.load(template), function(_) { throw 'Unexpected response'; },
|
PromiseWrapper.then(loader.load(template), function(_) { throw 'Unexpected response'; },
|
||||||
function(error) {
|
function(error) {
|
||||||
expect(error.message).toEqual('Failed to fetch url "base/foo"');
|
expect(error.message)
|
||||||
|
.toEqual('Failed to fetch url "base/foo.html"');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
xhr.flush();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('css', () => {
|
||||||
|
it('should load inline styles', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var template = new ViewDefinition({template: 'html', styles: ['style 1', 'style 2']});
|
||||||
|
loader.load(template).then((el) => {
|
||||||
|
expect(DOM.getInnerHTML(el))
|
||||||
|
.toEqual(
|
||||||
|
'<style type="text/css">style 1</style><style type="text/css">style 2</style>html');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should load templates through XHR', inject([AsyncTestCompleter], (async) => {
|
||||||
|
xhr.expect('base/foo.html', 'xhr template');
|
||||||
|
xhr.expect('base/foo-1.css', '1');
|
||||||
|
xhr.expect('base/foo-2.css', '2');
|
||||||
|
var template = new ViewDefinition({
|
||||||
|
templateAbsUrl: 'base/foo.html',
|
||||||
|
styles: ['i1'],
|
||||||
|
styleAbsUrls: ['base/foo-1.css', 'base/foo-2.css']
|
||||||
|
});
|
||||||
|
loader.load(template).then((el) => {
|
||||||
|
expect(DOM.getInnerHTML(el))
|
||||||
|
.toEqual(
|
||||||
|
'<style type="text/css">i1</style><style type="text/css">1</style><style type="text/css">2</style>xhr template');
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
xhr.flush();
|
xhr.flush();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should return a rejected Promise when XHR loading fails',
|
||||||
|
inject([AsyncTestCompleter], (async) => {
|
||||||
|
xhr.expect('base/foo.css', null);
|
||||||
|
var template = new ViewDefinition({template: '', styleAbsUrls: ['base/foo.css']});
|
||||||
|
PromiseWrapper.then(loader.load(template), function(_) { throw 'Unexpected response'; },
|
||||||
|
function(error) {
|
||||||
|
expect(error.message)
|
||||||
|
.toEqual('Failed to fetch url "base/foo.css"');
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
xhr.flush();
|
||||||
|
}));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user