0
# Built-in Directives
1
2
Comprehensive collection of directives for common templating patterns including conditional rendering, lists, styling, and performance optimization.
3
4
## Capabilities
5
6
### Conditional Rendering Directives
7
8
#### when Directive
9
10
Conditionally renders content based on a boolean condition with lazy evaluation.
11
12
```typescript { .api }
13
/**
14
* When `condition` is true, returns the result of calling `trueCase()`, else
15
* returns the result of calling `falseCase()` if `falseCase` is defined.
16
* @param condition - Condition to evaluate (any value)
17
* @param trueCase - Function called when condition is truthy
18
* @param falseCase - Optional function called when condition is falsy
19
* @returns Result of the appropriate template function
20
*/
21
function when<C, T, F = undefined>(
22
condition: C,
23
trueCase: (c: Exclude<C, Falsy>) => T,
24
falseCase?: (c: Extract<C, Falsy>) => F
25
): C extends Falsy ? F : T;
26
27
type Falsy = null | undefined | false | 0 | -0 | 0n | '';
28
```
29
30
**Usage Examples:**
31
32
```typescript
33
import { html } from 'lit-html';
34
import { when } from 'lit-html/directives/when.js';
35
36
const userStatus = (isLoggedIn: boolean, username?: string) => html`
37
<div>
38
${when(
39
isLoggedIn,
40
() => html`<span>Welcome, ${username}!</span>`,
41
() => html`<a href="/login">Please log in</a>`
42
)}
43
</div>
44
`;
45
```
46
47
#### choose Directive
48
49
Selects and renders one template from multiple options based on a key value.
50
51
```typescript { .api }
52
/**
53
* Chooses and renders one of many template functions based on a given value.
54
* @param value - The value to switch on
55
* @param cases - Array of [key, template] pairs to choose from
56
* @param defaultCase - Optional default template function
57
* @returns Result of the matching template function
58
*/
59
function choose<T, V>(
60
value: T,
61
cases: Array<[T, () => V]>,
62
defaultCase?: () => V
63
): V | typeof nothing;
64
```
65
66
**Usage Examples:**
67
68
```typescript
69
import { html } from 'lit-html';
70
import { choose } from 'lit-html/directives/choose.js';
71
72
// Switch on string values
73
const statusDisplay = (status: string) => html`
74
<div class="status">
75
${choose(status, [
76
['loading', () => html`<span class="spinner">Loading...</span>`],
77
['success', () => html`<span class="check">✓ Complete</span>`],
78
['error', () => html`<span class="error">✗ Failed</span>`],
79
], () => html`<span>Unknown status</span>`)}
80
</div>
81
`;
82
83
// Switch on number values
84
const priorityBadge = (priority: number) => html`
85
${choose(priority, [
86
[1, () => html`<span class="badge high">High</span>`],
87
[2, () => html`<span class="badge medium">Medium</span>`],
88
[3, () => html`<span class="badge low">Low</span>`],
89
])}
90
`;
91
92
// Without default case
93
const iconTemplate = (iconType: 'home' | 'user' | 'settings') => html`
94
${choose(iconType, [
95
['home', () => html`<svg><!-- home icon --></svg>`],
96
['user', () => html`<svg><!-- user icon --></svg>`],
97
['settings', () => html`<svg><!-- settings icon --></svg>`],
98
])}
99
`;
100
```
101
102
#### ifDefined Directive
103
104
Only renders an attribute if the value is not null or undefined.
105
106
```typescript { .api }
107
/**
108
* For AttributeParts, sets the attribute if the value is defined and removes
109
* the attribute if the value is undefined.
110
* @param value - Value to check and potentially set
111
* @returns The value or nothing if undefined
112
*/
113
function ifDefined(value: unknown): unknown;
114
```
115
116
**Usage Examples:**
117
118
```typescript
119
import { html } from 'lit-html';
120
import { ifDefined } from 'lit-html/directives/if-defined.js';
121
122
const link = (href?: string, title?: string) => html`
123
<a href="${ifDefined(href)}" title="${ifDefined(title)}">
124
Link text
125
</a>
126
`;
127
```
128
129
#### until Directive
130
131
Renders placeholder content until a promise resolves, then renders the resolved value.
132
133
```typescript { .api }
134
/**
135
* Renders one of a series of values, including Promises, to a Part.
136
* Values are rendered in priority order, with the first argument having the
137
* highest priority and the last argument having the lowest priority.
138
* @param values - Values to render in priority order
139
* @returns DirectiveResult for rendering
140
*/
141
function until(...values: unknown[]): DirectiveResult;
142
```
143
144
**Usage Examples:**
145
146
```typescript
147
import { html } from 'lit-html';
148
import { until } from 'lit-html/directives/until.js';
149
150
const asyncContent = html`
151
<div>
152
${until(
153
fetch('/api/data').then(r => r.json()).then(data => html`<pre>${JSON.stringify(data, null, 2)}</pre>`),
154
html`<div class="spinner">Loading...</div>`
155
)}
156
</div>
157
`;
158
```
159
160
### List Rendering Directives
161
162
#### repeat Directive
163
164
Efficiently renders lists with identity-based updates for optimal performance.
165
166
```typescript { .api }
167
/**
168
* A directive that repeats a series of values (usually templates) generated
169
* from an iterable, and updates those items efficiently when the iterable changes.
170
* @param items - The iterable to iterate over
171
* @param keyFnOrTemplate - Either a key function or the template function
172
* @param template - The template function (if keyFnOrTemplate is a key function)
173
* @returns DirectiveResult for rendering the list
174
*/
175
function repeat<T>(
176
items: Iterable<T>,
177
keyFnOrTemplate: KeyFn<T> | ItemTemplate<T>,
178
template?: ItemTemplate<T>
179
): DirectiveResult;
180
181
type KeyFn<T> = (item: T, index: number) => unknown;
182
type ItemTemplate<T> = (item: T, index: number) => unknown;
183
```
184
185
**Usage Examples:**
186
187
```typescript
188
import { html } from 'lit-html';
189
import { repeat } from 'lit-html/directives/repeat.js';
190
191
// Simple list without keys
192
const simpleList = (items: string[]) => html`
193
<ul>
194
${repeat(items, (item) => html`<li>${item}</li>`)}
195
</ul>
196
`;
197
198
// List with keys for efficient updates
199
const userList = (users: User[]) => html`
200
<ul>
201
${repeat(
202
users,
203
(user) => user.id, // Key function
204
(user, index) => html`
205
<li class="user">
206
<span>${user.name}</span>
207
<span>#${index + 1}</span>
208
</li>
209
`
210
)}
211
</ul>
212
`;
213
```
214
215
#### map Directive
216
217
Transforms an iterable using a template function, similar to Array.map().
218
219
```typescript { .api }
220
/**
221
* Maps an iterable using a template function.
222
* @param items - The iterable to map over
223
* @param template - Function that returns a template for each item
224
* @returns DirectiveResult for rendering the mapped items
225
*/
226
function map<T>(
227
items: Iterable<T>,
228
template: (item: T, index: number) => unknown
229
): DirectiveResult;
230
```
231
232
#### join Directive
233
234
Joins rendered items with a separator template.
235
236
```typescript { .api }
237
/**
238
* Joins an array of templates with a separator template.
239
* @param items - Array of templates to join
240
* @param joiner - Separator template to insert between items
241
* @returns DirectiveResult for rendering the joined content
242
*/
243
function join<I, J>(
244
items: Iterable<I>,
245
joiner: (index: number) => J
246
): DirectiveResult;
247
```
248
249
#### range Directive
250
251
Renders a range of numbers using a template function.
252
253
```typescript { .api }
254
/**
255
* Renders a range of integers from startAt to endAt (exclusive).
256
* @param startAt - Starting number (inclusive)
257
* @param endAt - Ending number (exclusive)
258
* @param template - Function to render each number
259
* @returns DirectiveResult for rendering the range
260
*/
261
function range<T>(
262
startAt: number,
263
endAt: number,
264
template: (item: number, index: number) => T
265
): DirectiveResult;
266
```
267
268
### Styling Directives
269
270
#### classMap Directive
271
272
Applies dynamic CSS classes based on an object of class names and boolean values.
273
274
```typescript { .api }
275
/**
276
* A directive that applies dynamic CSS classes.
277
* @param classInfo - Object mapping class names to boolean values
278
* @returns DirectiveResult for applying classes
279
*/
280
function classMap(classInfo: ClassInfo): DirectiveResult;
281
282
interface ClassInfo {
283
readonly [name: string]: string | boolean | number;
284
}
285
```
286
287
**Usage Examples:**
288
289
```typescript
290
import { html } from 'lit-html';
291
import { classMap } from 'lit-html/directives/class-map.js';
292
293
const button = (isPrimary: boolean, isDisabled: boolean) => html`
294
<button class=${classMap({
295
'btn': true,
296
'btn-primary': isPrimary,
297
'btn-secondary': !isPrimary,
298
'disabled': isDisabled
299
})}>
300
Click me
301
</button>
302
`;
303
```
304
305
#### styleMap Directive
306
307
Applies dynamic inline styles based on an object of CSS properties and values.
308
309
```typescript { .api }
310
/**
311
* A directive that applies CSS properties to an element.
312
* @param styleInfo - Object mapping CSS properties to values
313
* @returns DirectiveResult for applying styles
314
*/
315
function styleMap(styleInfo: StyleInfo): DirectiveResult;
316
317
interface StyleInfo {
318
readonly [name: string]: string | number | undefined | null;
319
}
320
```
321
322
**Usage Examples:**
323
324
```typescript
325
import { html } from 'lit-html';
326
import { styleMap } from 'lit-html/directives/style-map.js';
327
328
const coloredBox = (color: string, size: number) => html`
329
<div style=${styleMap({
330
backgroundColor: color,
331
width: `${size}px`,
332
height: `${size}px`,
333
borderRadius: '4px'
334
})}>
335
Colored box
336
</div>
337
`;
338
```
339
340
### Performance and Caching Directives
341
342
#### cache Directive
343
344
Caches rendered templates by key for efficient switching between different templates.
345
346
```typescript { .api }
347
/**
348
* Enables fast switching between multiple templates by caching the DOM they render.
349
* @param value - Key to cache the template by
350
* @returns DirectiveResult for caching
351
*/
352
function cache(value: unknown): DirectiveResult;
353
```
354
355
#### guard Directive
356
357
Only re-renders when dependencies change, providing performance optimization.
358
359
```typescript { .api }
360
/**
361
* Prevents re-evaluation of a template function until one or more of its dependencies changes.
362
* @param dependencies - Values to check for changes
363
* @param valueFn - Function that returns the template when dependencies change
364
* @returns Result of valueFn or cached result
365
*/
366
function guard(dependencies: unknown[], valueFn: () => unknown): unknown;
367
```
368
369
#### keyed Directive
370
371
Associates a template with a key for efficient updates when the key changes.
372
373
```typescript { .api }
374
/**
375
* Associates a renderable value with a unique key. When the key changes, the
376
* previous DOM is removed and a new DOM is rendered in its place.
377
* @param key - Unique key for the template
378
* @param value - Value to render
379
* @returns DirectiveResult for keyed rendering
380
*/
381
function keyed(key: unknown, value: unknown): DirectiveResult;
382
```
383
384
#### live Directive
385
386
Sets properties or attributes only when they differ from the live DOM value.
387
388
```typescript { .api }
389
/**
390
* Checks binding values against live DOM values, instead of previously bound
391
* values, when determining whether to update the value.
392
* @param value - Value to bind
393
* @returns DirectiveResult for live binding
394
*/
395
function live(value: unknown): DirectiveResult;
396
```
397
398
### Async Rendering Directives
399
400
#### asyncAppend Directive
401
402
Appends values from an async iterable as they become available.
403
404
```typescript { .api }
405
/**
406
* Renders values from an async iterable, appending each new value after the previous.
407
* @param asyncIterable - The async iterable to render from
408
* @param mapper - Optional function to transform each value
409
* @returns DirectiveResult for async appending
410
*/
411
function asyncAppend<T>(
412
asyncIterable: AsyncIterable<T>,
413
mapper?: (value: T, index: number) => unknown
414
): DirectiveResult;
415
```
416
417
#### asyncReplace Directive
418
419
Replaces content with values from an async iterable as they become available.
420
421
```typescript { .api }
422
/**
423
* Renders values from an async iterable, replacing the previous value with each new value.
424
* @param asyncIterable - The async iterable to render from
425
* @param mapper - Optional function to transform each value
426
* @returns DirectiveResult for async replacement
427
*/
428
function asyncReplace<T>(
429
asyncIterable: AsyncIterable<T>,
430
mapper?: (value: T, index: number) => unknown
431
): DirectiveResult;
432
```
433
434
### DOM Manipulation Directives
435
436
#### ref Directive
437
438
Provides a reference to a rendered element for direct DOM manipulation.
439
440
```typescript { .api }
441
/**
442
* Sets the value of a Ref object or calls a ref callback with the element it's bound to.
443
* @param refOrCallback - Ref object or callback function
444
* @returns DirectiveResult for ref binding
445
*/
446
function ref(refOrCallback: Ref | RefCallback): DirectiveResult;
447
448
type RefCallback = (el: Element | undefined) => void;
449
450
interface Ref<T = Element> {
451
readonly value: T | undefined;
452
}
453
454
function createRef<T = Element>(): Ref<T>;
455
```
456
457
**Usage Examples:**
458
459
```typescript
460
import { html, render } from 'lit-html';
461
import { ref, createRef } from 'lit-html/directives/ref.js';
462
463
const myRef = createRef<HTMLInputElement>();
464
465
const template = html`
466
<input ${ref(myRef)} type="text" />
467
<button @click=${() => myRef.value?.focus()}>Focus Input</button>
468
`;
469
```
470
471
#### templateContent Directive
472
473
Renders the content of a template element.
474
475
```typescript { .api }
476
/**
477
* Renders the content of a template element as HTML.
478
* @param templateElement - The template element to render
479
* @returns DirectiveResult for rendering template content
480
*/
481
function templateContent(templateElement: HTMLTemplateElement): DirectiveResult;
482
```
483
484
### Unsafe Content Directives
485
486
**Security Warning**: These directives render raw content and can introduce XSS vulnerabilities if used with untrusted input.
487
488
#### unsafeHTML Directive
489
490
Renders raw HTML content without escaping.
491
492
```typescript { .api }
493
/**
494
* Renders the result as HTML, rather than text.
495
* @param value - HTML string to render (must be trusted)
496
* @returns DirectiveResult for rendering HTML
497
*/
498
function unsafeHTML(value: string | typeof nothing | typeof noChange): DirectiveResult;
499
```
500
501
#### unsafeSVG Directive
502
503
Renders raw SVG content without escaping.
504
505
```typescript { .api }
506
/**
507
* Renders the result as SVG, rather than text.
508
* @param value - SVG string to render (must be trusted)
509
* @returns DirectiveResult for rendering SVG
510
*/
511
function unsafeSVG(value: string | typeof nothing | typeof noChange): DirectiveResult;
512
```
513
514
#### unsafeMathML Directive
515
516
Renders raw MathML content without escaping.
517
518
```typescript { .api }
519
/**
520
* Renders the result as MathML, rather than text.
521
* @param value - MathML string to render (must be trusted)
522
* @returns DirectiveResult for rendering MathML
523
*/
524
function unsafeMathML(value: string | typeof nothing | typeof noChange): DirectiveResult;
525
```
526
527
## Import Patterns
528
529
All directives are imported from individual modules:
530
531
```typescript
532
// Individual directive imports
533
import { repeat } from 'lit-html/directives/repeat.js';
534
import { classMap } from 'lit-html/directives/class-map.js';
535
import { styleMap } from 'lit-html/directives/style-map.js';
536
import { when } from 'lit-html/directives/when.js';
537
import { until } from 'lit-html/directives/until.js';
538
import { guard } from 'lit-html/directives/guard.js';
539
import { ref, createRef } from 'lit-html/directives/ref.js';
540
541
// Use in templates
542
const template = html`
543
<div class=${classMap(classes)} style=${styleMap(styles)}>
544
${repeat(items, (item) => item.id, (item) => html`<span>${item.name}</span>`)}
545
</div>
546
`;
547
```