Commit 7f8c3afc authored by S Anand's avatar S Anand

ENH: Templates allow access to source node. Fixes #169

parent 8cc54cb5
Pipeline #87297 failed with stage
in 2 minutes and 28 seconds
<div>sum(<%= JSON.stringify($data.x) %>) = <%= _.sum($data.x) %></div>
...@@ -21,6 +21,9 @@ This displays `Your platform is ...` and shows the userAgent just below the scri ...@@ -21,6 +21,9 @@ This displays `Your platform is ...` and shows the userAgent just below the scri
Note: the `<template>` tag is not supported by Internet Explorer. Use Note: the `<template>` tag is not supported by Internet Explorer. Use
`<script type="text/html">` for IE compatibility. `<script type="text/html">` for IE compatibility.
## $.template variables
Templates can access any global variable. You can pass additional variables Templates can access any global variable. You can pass additional variables
using as `.template({var1: value, var2: value, ...})`. For example: using as `.template({var1: value, var2: value, ...})`. For example:
...@@ -38,6 +41,45 @@ using as `.template({var1: value, var2: value, ...})`. For example: ...@@ -38,6 +41,45 @@ using as `.template({var1: value, var2: value, ...})`. For example:
To re-render the template, run `.template(data)` again with different data. To re-render the template, run `.template(data)` again with different data.
Templates can also use these default variables:
- `obj`: the full data object passed to the template
- `$node`: the generating `<template>` element as a jQuery object
- `$node.attr('class')` returns the class of the template
- `$node.data('key')` returns `data-key` in `<template data-key="...">`
- `$data`: a shortcut for `$node.data()`.
`$data.key` is the same as `$node.data('key')`
If you pass `obj`, `$node` or `$data` explicitly to `.template({...})`, it
overrides the default variables. The values you pass take priority.
You can pass any JSON object as a data attribute. In the example below,
`data-list` and `data-obj` are interpreted as JSON objects:
<!-- render:html -->
```html
<template class="datavar" data-list="[1,2,3]" data-obj="{x:1,y:[2,3]}">
list = <%= JSON.stringify($data.list) %>,
obj = <%= JSON.stringify($data.obj) %>,
</template>
<script>
$('.datavar').template()
</script>
```
This is particularly useful with [external sources](#template-external-source).
For example, using an external [datavars.html](datavars.html) template:
<!-- render:html -->
```html
<template class="datavars" src="datavars.html" data-x="[1,2]"></template>
<template class="datavars" src="datavars.html" data-x="[3,4,5]"></template>
<script>
$('.datavars').template()
</script>
```
## $.template subtemplates ## $.template subtemplates
You can use sub-templates as follows: You can use sub-templates as follows:
...@@ -62,7 +104,8 @@ You can use sub-templates as follows: ...@@ -62,7 +104,8 @@ You can use sub-templates as follows:
(This is typically used by sub-templates.) (This is typically used by sub-templates.)
`data-template-item=".row"` creates a function `item()` inside `.main-template`. `data-template-item=".row"` creates a function `item()` inside `.main-template`.
Calling `item()` renders `.roww` as a sub-template. Calling `item()` renders `.row` as a sub-template.
**Notes**: **Notes**:
......
...@@ -103,9 +103,11 @@ function make_template_sync($this, html, data, default_options) { ...@@ -103,9 +103,11 @@ function make_template_sync($this, html, data, default_options) {
// $this.data(_compiled) has the compiled template. This adds sub-template // $this.data(_compiled) has the compiled template. This adds sub-template
// variables from data-template-* attributes. // variables from data-template-* attributes.
$this.data(_compiled, function (subtemplate_data) { $this.data(_compiled, function (subtemplate_data) {
subtemplate_data = _.extend(subtemplate_data || {}, _.mapValues(subtemplates($this), function (selector) { subtemplate_data = _.extend(
return $(selector).data(_compiled) {$node: $this, $data: $this.data()},
})) _.mapValues(subtemplates($this), function (selector) { return $(selector).data(_compiled) }),
subtemplate_data || {}
)
return compiled_template(subtemplate_data) return compiled_template(subtemplate_data)
}) })
......
<%= data.join(' ') %> <%= data.join(',') %>
<!-- Ensure that these variables exist -->
<% $node %> <!-- The target node -->
<% $node.data('x').toLowerCase() %> <!-- ... having data-x=".." -->
<% $data.x.toLowerCase() %> <!-- same as $data.x -->
...@@ -39,6 +39,8 @@ async function run_puppeteer() { ...@@ -39,6 +39,8 @@ async function run_puppeteer() {
args: ['--no-sandbox'] args: ['--no-sandbox']
}) })
const page = await browser.newPage() const page = await browser.newPage()
// Note: if there's a console error, msg.type == 'error'
// msg.args has the error arguments.
page.on('console', msg => console.log(msg.text)) // eslint-disable-line no-console page.on('console', msg => console.log(msg.text)) // eslint-disable-line no-console
const paths = glob.sync('test/test-*.html') const paths = glob.sync('test/test-*.html')
for (let i = 0; i < paths.length; i++) { for (let i = 0; i < paths.length; i++) {
......
...@@ -60,8 +60,8 @@ ...@@ -60,8 +60,8 @@
$('#t2').one('template', function (e) { $('#t2').one('template', function (e) {
var $divs = e.target.filter('div') var $divs = e.target.filter('div')
t.equal($divs.length, list.length, 'Correct number of nodes are created') t.equal($divs.length, list.length, 'Correct number of nodes are created')
var text = $divs.map(function () { return this.innerHTML }).get().join(' ') var text = $divs.map(function () { return this.innerHTML }).get().join(',')
t.equal(text, list.join(' '), 'Template content is correct') t.equal(text, list.join(','), 'Template content is correct')
t.deepEqual(e.templatedata, { list: list }) t.deepEqual(e.templatedata, { list: list })
$divs.attr('class', 'my-unique-item') $divs.attr('class', 'my-unique-item')
t.equal($('.my-unique-item').length, 3, 'Repeated calls over-write the same node') t.equal($('.my-unique-item').length, 3, 'Repeated calls over-write the same node')
...@@ -70,12 +70,12 @@ ...@@ -70,12 +70,12 @@
}) })
</script> </script>
<template id="t3" src="sample-template.html"></template> <template id="t3" data-x="hi" src="sample-template.html"></template>
<script> <script>
tape('$().template() renders src= via AJAX load', function (t) { tape('$().template() renders src= via AJAX load', function (t) {
var data = { data: ['x', 'y'] } var data = { data: ['x', 'y'] }
$('#t3').one('template', function (e) { $('#t3').one('template', function (e) {
t.equal(text(e.target), data.data.join(' ')) t.equal(text(e.target), data.data.join(','))
t.deepEqual(e.templatedata, data) t.deepEqual(e.templatedata, data)
t.end() t.end()
}).template(data) }).template(data)
...@@ -83,13 +83,13 @@ ...@@ -83,13 +83,13 @@
</script> </script>
<template id="t4" src="nonexistent.html"> <template id="t4" src="nonexistent.html">
<%= xhr.status %>: Not found. <%= data.join(' ') %> <%= xhr.status %>: Not found. <%= data.join(',') %>
</template> </template>
<script> <script>
tape('$().template() renders contents if src= returns an error', function (t) { tape('$().template() renders contents if src= returns an error', function (t) {
var data = { data: ['x', 'y'] } var data = { data: ['x', 'y'] }
$('#t4').one('template', function (e) { $('#t4').one('template', function (e) {
t.equal(text(e.target), '404: Not found. x y') t.equal(text(e.target), '404: Not found. x,y')
t.deepEqual(e.templatedata.data, data.data) t.deepEqual(e.templatedata.data, data.data)
t.equal(e.templatedata.xhr.status, 404) t.equal(e.templatedata.xhr.status, 404)
t.end() t.end()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment