Function for building entirely data-driven idempotent components/UI with D3.
once(node) // limit to this node ('div', { results: [1, 2, 3] }) // creates one div (with the specified datum) ('li', key('results')) // creates three li (with datum 1, 2, 3 respectively) ('a', inherit) // creates anchor in each li (with parent datum) .text(String) // sets the text in anchor to the datum
The first time you call once(node | string)
it essentially selects that element and limits the scope of subsequent operations to that.
Subsequents calls generate a D3 join using the syntax (selector, data)
. The selector can be:
foo.bar.baz
). Classes are fine too and will be added to the final elements created.The data is the same as what you would normally use to generate a join (array of items, or function), with some convenient defaults: if you pass an object, number or boolean it'll be converted to a single-valued array, meaning "create one element with this as the datum". If you pass in a falsy, it defaults to empty array "meaning removing all elements of this type".
The return value is essentially a D3 join selection (enter/update/exit), so you can continue to customise using .text
, .classed
, .attr
, etc. You can also access the elements added via .enter
and removed via .exit
.
There are two further optional arguments you can use (selector, data[, key[, before]])
. The key function has the exact same meaning as normal (how to key data), which D3 defaults to by index. The before parameter can be used to force the insertion before a specific element à la .insert(something, before)
as opposed to just .append(something)
.