# Directives
The `e:`-prefixed attributes: `e:for`, `e:if` / `e:elseif` / `e:else`,
`e:switch` / `e:case` / `e:default`, and `e:literal`.
Directives are `e:`-prefixed attributes. They compose with normal attributes on
the same element. On an element with both `e:if` and `e:for`, the `e:if` is
evaluated first: a false `e:if` means the element does not render at all, and a
true `e:if` allows `e:for` to iterate. It is all-or-nothing for the whole loop.
**`e:if` cannot filter individual rows.** It decides whether the loop runs, not
which items it runs over. To show a subset, filter the iterable, as below. Do
not render every row and hide some with a class or `display: none`: the rows
are still there, in the DOM and in the accessibility tree, and counts taken
from the list will be wrong.
### e:for
Iterates over any iterable. The result is reactive: updates patch the DOM in
place at the row level.
```ehtml
{user.name}
{index}: {user.name}
{key}: {lookup[key]}
```
**Filtering and shaping.** The right-hand side is an expression, so filter,
sort, or reshape the rows there. The loop re-evaluates the expression when
anything it read changes, and reconciles the new row set against the old one
by key, so a row present in both keeps its dom.
```ehtml
matches(t, view.filter))}>
{todo.title}
```
A helper works the same way. A function that builds its own array from the
rows, `feed(messages)` say, is live because the loop's evaluation runs the
helper, and the helper iterated the view. Whatever the expression reads on the
way, a tab, a search string, the view itself, becomes something the loop
follows.
`LiveView` supports `filter`, `sort`, `map`, `find`, `at`, `length`, and the
rest of the non-mutating Array surface directly, and each returns a plain
array. `todos.filter(...)` is the whole answer for a list already on screen;
nothing is re-fetched. (`recipes/search-filter` is the other case: a
server-side re-query for a result set too large to hold in the browser.)
Group with a flag on the row, not a loop inside a loop. Keep one flat loop and
compute the grouping fact for each row as you build the list:
```ehtml
line.id}>
{line.dayLabel}
{line.message.body}
```
`Map.groupBy` with a nested loop renders the same page and repaints all of it.
A `[key, rows]` entry holds a fresh inner array every time the expression is
evaluated, so the group compares unequal to the one before it, takes the
update path, and re-renders itself and every row nested inside. One arriving
row rebuilds its whole group, and with an animation on a row that is a visible
flicker. `recipes/grouped-feed` has the working shape, the helper that builds
the lines, and the measurement.
`for...of` and `for...in` work the same as in JavaScript: `of` iterates arrays
and other iterables; `in` iterates object keys, string characters, and similar.
The Elements runtime patches `for...of` at the row level. `for...in` re-renders
the whole list when the right side changes.
By default rows are keyed by the `id` field on each item. Provide an `id` and
the runtime diffs by it, patching only the rows that changed. Without an `id`,
rows key by object identity, so replacing the array with fresh objects (say, a
refetch) re-renders every row.
Use `e:key` to supply your own key function when a row has no `id`, or when the
stable key isn't a field on the row, such as iterating `Object.entries`,
composite keys, and so on. It takes the iteration value and returns a `string` or
`number`:
```ehtml
item.id}>
{index} - {item.description}
```
The key function's parameter is the `e:for` iteration value, typed the same as
the loop binding, so a wrong destructure or a missing field is a compile error.
`e:key` pairs with `e:for` on the same element (either order).
### e:if / e:elseif / e:else
```ehtml
loading
error: {error.message}
ready
```
Branches must be siblings. Whitespace between them is allowed.
A directive applies to one element. To put several siblings under one
condition, wrap them in an element.
```ehtml
```
`` is not supported. The browser doesn't automatically render the
content of a `` element: it parses the content into a separate,
hidden fragment that stays off the page until a script copies it in. An
`e:if` on a `` would show nothing, and the page could not hydrate
what is inside it.
### e:switch / e:case / e:default
Parent holds the expression, children are cases.
```ehtml
activepausedunknown
```
### e:literal
`{...}` is an expression inside every element, `
```
In a `
```
A `