From e24ff8f8aad707d9e721d7d1a6286fcbf0f24f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Tue, 9 Jul 2019 09:45:43 +0200 Subject: [PATCH] [IMP] qweb: add renderToString method closes #230 --- doc/qweb.md | 7 +++++++ src/qweb_core.ts | 19 ++++++++++++++++++- tests/helpers.ts | 15 ++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/doc/qweb.md b/doc/qweb.md index a6bc9f02..9e0787dc 100644 --- a/doc/qweb.md +++ b/doc/qweb.md @@ -122,6 +122,13 @@ It's API is quite simple: const vnode = qweb.render("App", component); ``` +- **`renderToString(name, context)`**: renders a template, but returns an html + string. + + ```js + const str = qweb.renderToString("someTemplate", somecontext); + ``` + - **`register(name, Component)`**: static function to register an OWL Component to QWeb's global registry. Globally registered Components can be used in templates (see the `t-component` directive). This is useful for commonly used diff --git a/src/qweb_core.ts b/src/qweb_core.ts index e7bf6c24..efcd312c 100644 --- a/src/qweb_core.ts +++ b/src/qweb_core.ts @@ -1,4 +1,4 @@ -import { VNode, h } from "./vdom"; +import { VNode, h, patch } from "./vdom"; import { QWebVar, compileExpr } from "./qweb_expressions"; import { EventBus } from "./event_bus"; @@ -288,6 +288,23 @@ export class QWeb extends EventBus { return template.fn.call(this, context, extra); } + /** + * Render a template to a html string. + * + * Note that this is more limited than the `render` method: it is not suitable + * to render a full component tree, since this is an asynchronous operation. + * This method can only render templates without components. + */ + renderToString(name: string, context: EvalContext = {}): string { + const vnode = this.render(name, context); + if (vnode.sel === undefined) { + return vnode.text!; + } + const node = document.createElement(vnode.sel); + const result = patch(node, vnode); + return (result.elm).outerHTML; + } + _compile(name: string, elem: Element, parentContext?: Context): CompiledTemplate { const isDebug = elem.attributes.hasOwnProperty("t-debug"); const ctx = new Context(name); diff --git a/tests/helpers.ts b/tests/helpers.ts index 60d95b1a..1a783569 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -68,9 +68,22 @@ export function renderToDOM( return result.elm as HTMLElement; } +/** + * Render a template to an html string. The big difference with the + * renderToString method in QWeb is that we use the renderToDom method, which + * snapshots the resulting template function. Doing so gives us a large body + * of reference to evaluate changes in the generated QWeb code. + * + * Note that the result of renderToString is guaranteed to be the same as the + * one from QWeb. + */ export function renderToString(qweb: QWeb, t: string, context: EvalContext = {}): string { const node = renderToDOM(qweb, t, context); - return node instanceof Text ? node.textContent! : node.outerHTML; + const result = node instanceof Text ? node.textContent! : node.outerHTML; + if (result !== qweb.renderToString(t, context)) { + throw new Error("HTML string returned by renderToString helper does not match QWeb render"); + } + return result; } // hereafter, we define two helpers to patch/unpatch the nextFrame utils. This