@@ -8,62 +8,33 @@ Add a static template function in your `x-element` definition in order to
88leverage automagical DOM generation and data binding:
99
1010``` javascript
11- static template (html , { map } ) {
11+ static template (html ) {
1212 return ({ options, selectedId }) => {
1313 return html `
1414 <select name =" my-options" >
15- ${ map (options, option => option .id , option => html `
16- <option value =" ${option.value}" ?selected =" ${option.id === selectedId}" >
17- ` )}
15+ ${ options .map (option => [
16+ option .id ,
17+ html ` <option value =" ${option.value}" ?selected =" ${option.id === selectedId}" >` ,
18+ ])}
1819 </select >
1920 ` ;
2021 };
2122}
2223```
2324
24- The following binding types are supported:
25+ The following bindings are supported:
2526
26- | Type | Example |
27- | :------------------ | :----------------------------------------- |
28- | attribute | ` <span id="target" foo="${bar}"></span> ` |
29- | attribute (boolean) | ` <span id="target" ?foo="${bar}"></span> ` |
30- | attribute (defined) | ` <span id="target" ??foo="${bar}"></span> ` |
31- | property | ` <span id="target" .foo="${bar}"></span> ` |
32- | content | ` <span id="target">${foo}</span> ` |
33-
34- Emulates:
35-
36- ``` javascript
37- const el = document .createElement (' div' );
38- el .attachShadow ({ mode: ' open' });
39- el .innerHTML = ' <span id="target"></span>' ;
40- const target = el .shadowRoot .getElementById (' target' );
41-
42- // attribute value bindings set the attribute value
43- target .setAttribute (' foo' , bar);
44-
45- // attribute boolean bindings set the attribute to an empty string or remove
46- target .setAttribute (' foo' , ' ' ); // when bar is truthy
47- target .removeAttribute (' foo' ); // when bar is falsy
48-
49- // attribute defined bindings set the attribute if the value is non-nullish
50- target .setAttribute (' foo' , bar); // when bar is non-nullish
51- target .removeAttribute (' foo' ); // when bar is nullish
52-
53- // property bindings assign the value to the property of the node
54- target .foo = bar;
55-
56- // content bindings create text nodes for basic content
57- const text = document .createTextNode (' ' );
58- text .textContent = foo;
59- target .append (text);
60-
61- // content bindings append a child for singular, nested content
62- target .append (foo);
63-
64- // content binding maps and appends children for arrays of nested content
65- target .append (... foo);
66- ```
27+ | Binding | Template | Emulates |
28+ | :------------------ | :--------------------------- | :------------------------------------------------------------ |
29+ | -- | -- | ` const el = document.createElement('div'); ` |
30+ | attribute | ` <div foo="${bar}"></div> ` | ` el.setAttribute('foo', bar); ` |
31+ | attribute (boolean) | ` <div ?foo="${bar}"></div> ` | ` el.setAttribute('foo', ''); // if “bar” is truthy ` |
32+ | -- | -- | ` el.removeAttribute('foo'); // if “bar” is falsy ` |
33+ | attribute (defined) | ` <div ??foo="${bar}"></div> ` | ` el.setAttribute('foo', bar); // if “bar” is non-nullish ` |
34+ | -- | -- | ` el.removeAttribute('foo'); // if “bar” is nullish ` |
35+ | property | ` <div .foo="${bar}"></div> ` | ` el.foo = bar; ` |
36+ | content | ` <div>${foo}</div> ` | ` el.append(document.createTextNode(foo)) // if “bar” is text ` |
37+ | -- | -- | (see [ content binding] ( #content-binding ) for composition) |
6738
6839** Important note on serialization during data binding:**
6940
@@ -78,12 +49,6 @@ The following template languages are supported:
7849* ` html `
7950* ` svg `
8051
81- The following value updaters are supported:
82-
83- * ` map ` (can be used with content bindings)
84- * ` unsafe ` (can be used with content bindings)
85- * ` live ` (can be used with property bindings)
86-
8752** A note on non-primitive data:**
8853
8954Because DOM manipulation is * slow* — template engines do their best to avoid it
@@ -216,23 +181,6 @@ html`<div .foo="${bar}"></div>`;
216181// el.foo = bar;
217182```
218183
219- #### The ` live ` property binding
220-
221- You can wrap the property being bound in the ` live ` updater to ensure that each
222- ` render ` call will sync the template‘s value into the DOM. This is primarily
223- used to control form inputs.
224-
225- ``` js
226- const bar = ' something' ;
227- html ` <input .value =" ${live(bar)}" >` ;
228- // <input>
229- // el.value = bar;
230- ```
231-
232- The key difference to note is that the basic property binding will not attempt
233- to perform an update if ` value === lastValue ` . The ` live ` binding will instead
234- check if ` value === el.value ` whenever a ` render ` is kicked off.
235-
236184### Content binding
237185
238186The content binding does different things based on the value type passed in.
@@ -283,7 +231,7 @@ html`<div>${bar}</div>`;
283231
284232#### Array content binding
285233
286- When the content being bound is an array of template results, you get a mapping .
234+ When the content being bound is an array of template results, you get a list .
287235
288236``` js
289237const bar = [
@@ -300,14 +248,16 @@ html`<div>${bar}</div>`;
300248// <div><span>one</span><span>two</span></div>
301249```
302250
303- #### The ` map ` content binding
251+ #### Map content binding
304252
305- The ` map ` content binding adds some special behavior on top of the basic array
306- content binding. In particular, it _ keeps track_ of each child node based on
307- an ` identify ` function declared by the caller. This enables the template engine
308- to _ move_ child nodes under certain circumstances (versus having to constantly
309- destroy and recreate). And that shuffling behavior enables authors to animate
310- DOM nodes across such transitions.
253+ When the content being bound is an array of key-value map entries (where the
254+ ` key ` is a unique string within the list and the ` value ` is a template result),
255+ you get also list. But, this value will come with some special behavior on top
256+ of the basic array content binding. In particular, it _ keeps track_ of each
257+ child node based on the given ` key ` you declare. This enables the template
258+ engine to _ move_ child nodes under certain circumstances (versus having to
259+ constantly destroy and recreate). And that shuffling behavior enables authors to
260+ animate DOM nodes across such transitions.
311261
312262``` js
313263// Note that you can shuffle the deck without destroying / creating DOM.
@@ -318,41 +268,12 @@ const deck = [
318268];
319269const items = deck;
320270const identify = item => item .id ;
321- const callback = item => html ` <span >${ item .text } </span >` ;
322- const bar = map (items, identify, callback );
271+ const template = item => html ` <span >${ item .text } </span >` ;
272+ const bar = items . map (item => [ identify (item), template (item)] );
323273html ` <div >${ bar} </div >` ;
324274// <div><span>♥1</span>…<span>♣A</span></div>
325275```
326276
327- #### The ` unsafe ` content binding
328-
329- The ` unsafe ` content binding allows you to parse / instantiate text from a
330- trusted source. This should _ only_ be used to inject trusted content — never
331- user content.
332-
333- ``` js
334- const bar = ' <script>console.prompt("can you hear me now?")</script>' ;
335- html ` <div >${ unsafe (bar, ' html' )} </div >` ;
336- // <div><script>console.prompt("can you hear me now?")</script></div>
337- // console.prompt('can you hear me now?');
338-
339- const bar = ' <circle cx="50" cy="50" r="50"></circle>' ;
340- html `
341- <svg
342- xmlns =" http://www.w3.org/2000/svg"
343- viewBox =" 0 0 100 100" >
344- ${ unsafe (bar, ' svg' )}
345- </svg >
346- ` ;
347- //
348- // <svg
349- // xmlns="http://www.w3.org/2000/svg"
350- // viewBox="0 0 100 100">
351- // <circle cx="50" cy="50" r="50"></circle>
352- // </svg>
353- //
354- ```
355-
356277## Customizing your base class
357278
358279Following is a working example using [ lit-html] ( https://lit.dev ) :
0 commit comments