UNPKG

9.05 kBMarkdownView Raw
1# Rendering
2
3To render a Marko view, you need to `require` it.
4
5_example.js_
6
7```js
8var fancyButton = require("./components/fancy-button");
9```
10
11> **Note:** If you are targeting node.js, you will need to enable the [require extension](./installing.md#require-marko-views) in order to require `.marko` files or you will need to precompile all of your templates using [Marko CLI](https://github.com/marko-js/cli). If you are targeting the browser, you will need to use a bundler like [`lasso`](../lasso.md), [`webpack`](../webpack.md), [`browserify`](../browserify.md) or [`rollup`](../rollup.md).
12
13Once you have a view, you can pass input data and render it:
14
15_example.js_
16
17```js
18var button = require("./components/fancy-button");
19var html = button.renderToString({ label: "Click me!" });
20
21console.log(html);
22```
23
24The input data becomes available as `input` within a view, so if `fancy-button.marko` looked like this:
25
26_./components/fancy-button.marko_
27
28```marko
29<button>${input.label}</button>
30```
31
32The output HTML would be:
33
34```html
35<button>Click me!</button>
36```
37
38## Rendering methods
39
40We used the `renderToString` method above to render the view, but there are a number of different method signatures that can be used to render.
41
42Many of these methods return a [`RenderResult`](#renderresult) which is an object with helper methods for working with the rendered output.
43
44### `renderSync(input)`
45
46| params | type | description |
47| ------------ | ------------------------------- | -------------------------------------- |
48| `input` | `Object` | the input data used to render the view |
49| return value | [`RenderResult`](#renderresult) | The result of the render |
50
51Using `renderSync` forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.
52
53```js
54var view = require("./view"); // Import `./view.marko`
55var result = view.renderSync({});
56
57result.appendTo(document.body);
58```
59
60### `render(input)`
61
62| params | type | description |
63| ------------ | -------------------------------- | -------------------------------------- |
64| `input` | `Object` | the input data used to render the view |
65| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target |
66
67The `render` method returns an async `out` which is used to generate HTML on the server or a virtual DOM in the browser. In either case, the async `out` has a `then` method that follows the Promises/A+ spec, so it can be used as if it were a Promise. This promise resolves to a [`RenderResult`](#renderresult).
68
69```js
70var view = require("./view"); // Import `./view.marko`
71var resultPromise = view.render({});
72
73resultPromise.then(result => {
74 result.appendTo(document.body);
75});
76```
77
78### `render(input, callback)`
79
80| params | type | description |
81| -------------- | -------------------------------- | ---------------------------------------------- |
82| `input` | `Object` | the input data used to render the view |
83| `callback` | `Function` | a function to call when the render is complete |
84| callback value | [`RenderResult`](#renderresult) | The result of the render |
85| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target |
86
87```js
88var view = require("./view"); // Import `./view.marko`
89
90view.render({}, (err, result) => {
91 result.appendTo(document.body);
92});
93```
94
95### `render(input, stream)`
96
97| params | type | description |
98| ------------ | -------------------------------- | -------------------------------------- |
99| `input` | `Object` | the input data used to render the view |
100| `stream` | `WritableStream` | a writeable stream |
101| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target |
102
103The HTML output is written to the passed `stream`.
104
105```js
106var http = require("http");
107var view = require("./view"); // Import `./view.marko`
108
109http.createServer((req, res) => {
110 res.setHeader("content-type", "text/html");
111 view.render({}, res);
112});
113```
114
115### `render(input, out)`
116
117| params | type | description |
118| ------------ | -------------------------------- | -------------------------------------- |
119| `input` | `Object` | the input data used to render the view |
120| `out` | `AsyncStream`/`AsyncVDOMBuilder` | The async `out` to render to |
121| return value | `AsyncStream`/`AsyncVDOMBuilder` | The `out` that was passed |
122
123The `render` method also allows passing an existing async `out`. If you do this, `render` will not automatically end the async `out` (this allows rendering a view in the middle of another view). If the async `out` won't be ended by other means, you are responsible for ending it.
124
125```js
126var view = require("./view"); // Import `./view.marko`
127var out = view.createOut();
128
129view.render({}, out);
130
131out.on("finish", () => {
132 console.log(out.getOutput());
133});
134
135out.end();
136```
137
138### `renderToString(input)`
139
140| params | type | description |
141| ------------ | -------- | -------------------------------------- |
142| `input` | `Object` | the input data used to render the view |
143| return value | `String` | The HTML string produced by the render |
144
145Returns an HTML string and forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.
146
147```js
148var view = require("./view"); // Import `./view.marko`
149var html = view.renderToString({});
150
151document.body.innerHTML = html;
152```
153
154### `renderToString(input, callback)`
155
156| params | type | description |
157| -------------- | ----------- | -------------------------------------- |
158| `input` | `Object` | the input data used to render the view |
159| callback value | `String` | The HTML string produced by the render |
160| return value | `undefined` | N/A |
161
162An HTML string is passed to the callback.
163
164```js
165var view = require("./view"); // Import `./view.marko`
166
167view.renderToString({}, (err, html) => {
168 document.body.innerHTML = html;
169});
170```
171
172### `stream(input)`
173
174The `stream` method returns a node.js style stream of the output HTML. This method is available on the server, but is not available by default in the browser. If you need to use streams in the browser, you may `require('marko/stream')` as part of your client-side bundle.
175
176```js
177var fs = require("fs");
178var view = require("./view"); // Import `./view.marko`
179var writeStream = fs.createWriteStream("output.html");
180
181view.stream({}).pipe(writeStream);
182```
183
184## RenderResult
185
186### `getComponent()`
187
188### `getComponents(selector)`
189
190### `afterInsert(doc)`
191
192### `getNode(doc)`
193
194### `getOutput()`
195
196### `appendTo(targetEl)`
197
198### `insertAfter(targetEl)`
199
200### `insertBefore(targetEl)`
201
202### `prependTo(targetEl)`
203
204### `replace(targetEl)`
205
206### `replaceChildrenOf(targetEl)`
207
208## Global data
209
210If you need to make data available globally to all views that are rendered as the result of a call to one of the above render methods, you can pass the data as a `$global` property on the input data object. This object will be removed from `input` and merged into the `out.global` property.
211
212```js
213view.render({
214 $global: {
215 flags: ["mobile"]
216 }
217});
218```
219
220To prevent sensitive data to be accidentally shipped to the browser, by default **none of the keys** in `out.global` is going to be sent to the browser. If you want the data to be serialized and ship to the frontend you need to specify it in `serializedGlobals` inside the `$global` object and they persist across re-renderings.
221The values need to be serializable.
222
223```js
224app.get("/", (req, res) => {
225 const ua = req.get("User-Agent");
226 const isIos = !!ua.match(/iPad|iPhone/);
227 const isAndroid = !!ua.match(/Android/);
228
229 require("./index.marko").render(
230 {
231 $global: {
232 isIos, // isPad is serialized and available on the server and the browser in out.global.isPad
233 isAndroid, // isAndroid is serialized and available on the server and the browser in out.global.isAndroid
234 req, // req is going to be available only server side and will not be serialized because in not present in serializedGlobals below
235
236 serializedGlobals: {
237 isIos: true, // Tell marko to serialize isIos above
238 isAndroid: true // Tell marko to serialize isAndroid above
239 }
240 }
241 },
242 res
243 );
244});
245```
246
247Use `$global` with judgement. It is global and visible in any component.
248
249Check [this PR](https://github.com/marko-js/marko/pull/672) for more details.