Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IMP] template set config: getTemplate function #1580

Merged
merged 1 commit into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/reference/app.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ The `config` object is an object with some of the following keys:
templates (see [translations](translations.md))
- **`templates (string | xml document)`**: all the templates that will be used by
the components created by the application.
- **`getTemplate ((s: string) => Element | Function | string | void)`**: a function that will be called by owl when it
needs a template. If undefined is returned, owl looks into the app templates.
- **`warnIfNoStaticProps (boolean, default=false)`**: if true, Owl will log a warning
whenever it encounters a component that does not provide a [static props description](props.md#props-validation).

Expand Down
5 changes: 4 additions & 1 deletion src/runtime/template_set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface TemplateSetConfig {
translatableAttributes?: string[];
translateFn?: (s: string) => string;
templates?: string | Document | Record<string, string>;
getTemplate?: (s: string) => Element | Function | string | void;
}

export class TemplateSet {
Expand All @@ -22,6 +23,7 @@ export class TemplateSet {
dev: boolean;
rawTemplates: typeof globalTemplates = Object.create(globalTemplates);
templates: { [name: string]: Template } = {};
getRawTemplate?: (s: string) => Element | Function | string | void;
translateFn?: (s: string) => string;
translatableAttributes?: string[];
Portal = Portal;
Expand All @@ -39,6 +41,7 @@ export class TemplateSet {
}
}
}
this.getRawTemplate = config.getTemplate;
}

addTemplate(name: string, template: string | Element) {
Expand Down Expand Up @@ -77,7 +80,7 @@ export class TemplateSet {

getTemplate(name: string): Template {
if (!(name in this.templates)) {
const rawTemplate = this.rawTemplates[name];
const rawTemplate = this.getRawTemplate?.(name) || this.rawTemplates[name];
if (rawTemplate === undefined) {
let extraInfo = "";
try {
Expand Down
52 changes: 52 additions & 0 deletions tests/compiler/__snapshots__/template_set.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,55 @@ exports[`loading templates can load a few templates from an XMLDocument 2`] = `
}
}"
`;

exports[`loading templates getTemplate: element returned (2) 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;

let block1 = createBlock(\`<div>Hello World!</div>\`);

return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;

exports[`loading templates getTemplate: element returned 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;

let block1 = createBlock(\`<div>Hello World!</div>\`);

return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;

exports[`loading templates getTemplate: template string returned 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;

let block1 = createBlock(\`<div>Hello World!</div>\`);

return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;

exports[`loading templates getTemplate: undefined returned 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;

let block1 = createBlock(\`<div>Hello World!</div>\`);

return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
58 changes: 58 additions & 0 deletions tests/compiler/template_set.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,62 @@ describe("loading templates", () => {
context.addTemplates(xml);
expect(Object.keys(context.rawTemplates)).toEqual([]);
});

test("getTemplate: element returned", () => {
const context = new TestContext({
getTemplate: (name) => {
if (name === "main") {
const data = `<div>Hello World!</div>`;
const xml = new DOMParser().parseFromString(data, "text/xml");
return xml.firstChild as Element;
}
return;
},
});
const result = context.renderToString("main");
expect(result).toBe("<div>Hello World!</div>");
});

test("getTemplate: element returned (2)", () => {
const context = new TestContext({
getTemplate: (name) => {
if (name === "main") {
const doc = new Document();
const div = doc.createElement("div");
div.append(doc.createTextNode("Hello World!"));
return div;
}
return;
},
});
const result = context.renderToString("main");
expect(result).toBe("<div>Hello World!</div>");
});

test("getTemplate: template string returned", () => {
const context = new TestContext({
getTemplate: (name) => {
if (name === "main") {
return `<div>Hello World!</div>`;
}
return;
},
});
const result = context.renderToString("main");
expect(result).toBe("<div>Hello World!</div>");
});

test("getTemplate: undefined returned", () => {
const context = new TestContext({
getTemplate: () => {},
});
const data = `<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<div t-name="main">Hello World!</div>
</templates>`;
const xml = new DOMParser().parseFromString(data, "text/xml");
context.addTemplates(xml);
const result = context.renderToString("main");
expect(result).toBe("<div>Hello World!</div>");
});
});
Loading