Template plugin for D3js.
npm install d3-template-plugin(This version is meant for V4/V5 and has not been tested on V3 or earlier versions of D3)
This is version 2 of d3-template. If you have used version 1 before, please check out the explanation.
d3-template is a D3 plugin to support templates using D3's data binding mechanism. This means you can use D3's familiar functionality directly on or with your templates. Apply transitions or add event handlers to template elements with access to the bound data. Render new data on a template thereby updating attributes, styles, properties and text. Also new elements are added and superfluous elements are removed from repeating groups (D3's enter/exit update pattern). This works for both HTML as well as SVG elements both in the browser as well as within Node. Templates will normally be acting on the live DOM, but can be used on virtual DOM's (like jsdom) as well.
If you are looking for existing templating support like Handlebars, Mustache or Nunjucks have a look at d3-templating.
The following information is available:
* Usage
* Installing
* Features
* Limitations
* API Reference
* Details
* Repeating groups
* If groups
* Import templates
* Transitions
* Event handlers
* History
* Examples
* License
Templates look like they do in most other templating tools: rendering data by placing expressions within curly braces into HTML or SVG elements. These expressions are data functions (as described in the introduction of the D3 homepage) but lack an explicit return statement. The standard arguments d, i, nodes are present and this is set to the (Template) node being rendered.
The general usage is probably best described by an example (see example on bl.ocks.org):
``HTML
{{Name: ${d.name}}}
{{Birthdate: ${d3.timeFormat("%-d %B %Y")(d.date)}}}
Honours given name to:
// Add event handler to list element before template creation
d3.select("#person ul li")
.on("click", function(d, i, nodes) {
// d will be entry from the honours.given array
// i will be current index
// nodes will be the li nodes
// this will refer to the current node (ie nodes[i])
console.log(d, i, nodes.length);
})
;
// Turn selection into a template
// This will remove some elements from the DOM as well as add some attributes to elements
// for identification.
d3.select("#person")
.template()
;
// ...
// Render data onto earlier created template
// Information retrieved from https://en.wikipedia.org/wiki/Alan_Turing#Awards,_honours,_recognition,_and_tributes
d3.select("#person")
.render({
name: "Alan Turing",
birthdate: new Date(1912, 5, 23),
deathdate: new Date(1954, 5, 7),
honours: {
received: [
"Order of the British Empire",
"Fellow of the Royal Society"
],
given: [
"Good–Turing frequency estimation",
"Turing completeness",
"Turing degree",
"Turing fixed-point combinator",
"Turing Institute",
"Turing Lecture",
"Turing machine examples",
"Turing patterns",
"Turing reduction",
"Turing switch"
]
}
})
;
// The click event handler is now present on all li elements
`
When rendering data onto a template which is already rendered, the new data will be bound and elements will be updated accordingly. A transition can be created to animate the new data rendering.
To install via npm use npm install d3-template-plugin. Or use/install directly using unpkg.
The following features are present:
* Data rendering onto attributes and text directly.
* Data can also be rendered on attributes, styles, properties or class fields indirectly (through data-attr-, data-style-, data-prop- and data-class-). Properties can be useful for setting the value or checked property of HTML input elements for example. The indirect rendering is especially useful for SVG because most browsers do not like 'invalid' attribute values:
`SVG
`
* Repeating and conditional groups (through data-repeat and data-if attribute).with
* A scope group similar to the Javascript statement (through data-with attribute).repeat
* Other templates can be imported. Which template gets imported can be decided on render time based on the bound data.
* Possibility to overwrite the template attribute names with custom names. If for example , if and with is preferred over de long names, this can be specified when creating a template. Although such custom attributes are not compliant with HTML5 or SVG specifications, most browsers will accept it without complaining.selection.on()
* Render only part of a template by rendering on a group element (repeat, if, with or import).
* Event handlers added onto elements before the template was created (using ), will be (re)applied when rendering the template.
* Rendering can be done within a transition allowing animations.
* Tweens (for attribute, style, property or text) can also be used in combination with a transition by providing a tween data function.
The following known limitations are present:
* Data references (the curly braces) can only be applied to the full element or the full attribute value. (For completeness: Surrounding whitespace is allowed for elements or attributes, but will be removed.)
`HTML
...
{{jobCount}} jobs
{{d.jobCount + " jobs"}}
{{${d.jobCount} jobs}}
{{d.jobCount}} jobs
{{d.jobCount}} jobs
`
* There should be none or one child element for a grouping element (repeat, if or with). If more child elements are needed, these have to be wrapped in a container element. If only text is present, this has to be wrapped in a container element as well. An exception will be thrown during parsing of the template if such invalid structures are present. (Having no child element on a group is actually useless, but allowed for convenience during development.)
`HTML
}}* Grouping elements (
repeat, if or with) can not be combined on the same element. One has to be wrapped inside the other.
* An import element can only be combined with the with grouping to scope (or map) the data for the imported template. Combining import with repeat or if is not allowed.
* There is no else for if groupings. A second if needs to be added (with a negated expression) or an import could be used (see if groups explanation).
* Setting properties of (for example) HTML input elements can not be done using transitions, since D3 transitions do not support it. It is however possible to create a tween data function.API Reference
# d3.template(selection[, options]) <>
Creates a template from the specified selection. The selection might be changed as a result of this. Attributes or text consisting of template references will be removed. Child elements of an element containing a valid grouping attribute (
data-repeat, data-if or data-with) will be removed. Different elements will have an attribute (data-d3t7s or data-d3t7b) applied for identification purposes.If options is specified it should be an object containing properties describing the template attribute names being used. Only the properties that need custom values should be present. The following are the default options values:
`Javascript
{
repeatAttribute: "data-repeat",
ifAttribute: "data-if",
withAttribute: "data-with",
importAttribute: "data-import",
indirectAttributePrefix: "data-attr-",
indirectStylePrefix: "data-style-",
indirectPropertyPrefix: "data-prop-",
indirectClassPrefix: "data-class-"
}
`# d3.render(selection, data) <>
Renders data onto the specified selection. If no template has been created from selection an exception is thrown. If selection is part of a (larger) template and selection is a grouping element like
repeat, if, with or import then rendering will be performed. Do remember that rendering on the template (root) will overwrite all template elements. So updating parts of a template should be done with caution.# selection.template([options]) <>
Creates a template from this selection. The following are all equivalent:
`Javascript
d3.template(selection, options);
selection.template(options);
selection.call(d3.template, options)
`Renders data onto this selection. The following are all equivalent:
`Javascript
d3.render(selection, data);
selection.render(data);
selection.call(d3.render, data);
`Renders data onto this transition. The following are all equivalent:
`Javascript
d3.render(transition, data);
transition.render(data);
transition.call(d3.render, data);
`Details
$3
Repeating groups can only be used with arrays as data. The array will be bound to the element when rendered. The group's child element will be appended conform the regular D3 enter/exit pattern. A copy of the child element will be rendered for every array element provided. It will have the corresponding array element bound as data.
`HTML
- {{d}}
`To use the index or length of the repeat group, use the D3 typical
i or nodes parameters:`HTML
- {{
${i + 1} of ${nodes.length}}} - {{d}}
`$3
If groups are conditional elements within a template. It allows a child element to be rendered (or not) based on a condition. If the condition expression evaluaties to a thruthy value, the child is rendered. Otherwise no child will be rendered (an existing child will be removed).
`HTML
...
There are no employees in this company.
`As can be seen in the example above, there is no
else clause for if groups. Another approach would be to have a dynamic import which chooses the correct template.`HTML
`$3
It is possible to import another template. The data bound to the element during rendering can be used to dynamically decide which template gets imported. The data function for the
data-import attribute should answer either a (CSS) selector or a D3 selection. The element can not have children in the template (the imported template will render the child/children).`HTML
`In the example above templates have an
id attribute. According to the HTML/SVG specifications these should be unqiue. These id attributes will therefore not be present when the template is rendered on an import. Only the original template will have it.An import can be combined with
with grouping to scope (or map) the data onto the imported template.`HTML
{{d.name}}
`The tween data function should return a function accepting a single parameter
t in accordance with the regular tween functions attrTween, styleTween and/or tween.A tween data function is to be used in combination with rendering on a transition. If a tween data function is specified within a template, but the render is performed without an active transition then the final tween result is rendered directly (ie the value returned by calling the tween data function with value
1.0).$3
If event handlers are applied to a selection before a template is being created from it, these event handlers will be applied to the rendered result as well. When an event handler is called it will receive the normal D3 style arguments
d, i, nodes and this will be set to the node receiving the event.`HTML
- {{d.english}}
`History
d3-template was created to remove some of the burden of having to create each and every DOM element when applying the enter/exit update pattern. For version 1 additional tooling was foreseen which would create data structures based on the templates. Work the other way around so to say. This did not work out as expected and adding the much needed filters did not help. So with version 2 the approach where the template expressions are fields (and filters) is dropped. Beginning with version 2 template expressions are Javascript expressions with parameters
d, i, nodes` defined as in D3 data functions. Version 1 code will break on the version 2 plugin. Sorry for any inconvenience. The new expressions should have a higher expressiveness and should be eassier to debug. As with version 1: hopefully this is a useful plugin for you.