# Attributes Typed attributes on a template constructor, reactive expression blocks, and the two-way bindings Elements installs on form controls. Attributes go in `()` on the opening tag. Each attribute is `public` (the default) or `private`. Optional attributes use `?`. Attributes can have initializers that reference other attributes, and declaration order does not matter. `private` attributes cannot be provided by callers, but they can be mutated inside the template scope. ```ehtml

{greeting}

``` Attributes are fully typed and integrated with the codebase's tooling: rename, find-references, go-to-definition, and type checking work across templates and TypeScript alike. ## Layout One or two attributes sit on the tag line. ```ehtml ``` Three or more go one per line. The `(` stays on the tag line, each attribute gets a line and a trailing comma, and `)>` closes at the tag's indent. ```ehtml ``` The trailing comma is optional and worth writing: adding an attribute then touches one line instead of two. Regular attributes stay on the tag line ahead of the `(`, and a long one goes after the `)`. ```ehtml , view: View, private draft: Draft = { title: "" }, ) oninit={() => window.addEventListener("popstate", () => onPopState(view))}> ``` Do not hang the list off the tag name's indent: ```ehtml ``` Every line there starts at a different column, so the constructor does not read as a list and `class` does not read as separate from it. The rule is the one TypeScript uses for a parameter list: open on the declaration line, one item per line, close at the declaration's indent. Attributes are reactive automatically, including across template boundaries: ```ehtml done: {tasks.filter(t => t.done).length} ``` Toggling the checkbox in `` updates the count in `` immediately. **Attributes live on the root tag only.** An attribute list on a non-root element (e.g. `
`) is invalid. **A union inside an object default needs a cast.** The declared type does not currently reach into an object literal used as a default, so a union field in one is inferred as its widened type and rejected: ```ehtml ``` Grouping template state into one object is the usual way to keep it mutable: a handler can mutate an object's fields and the change is live, while reassigning a plain attribute inside a handler is not (see Reactivity). The object is therefore often the right shape, and the cast is the price until this is fixed. ## Expressions `{ ... }` is a TypeScript expression. Allowed as element children and attribute values. ```ehtml

{title}

{label}

{users.length === 0 ? "empty" : `${users.length} users`}

``` For raw HTML output without escaping, use `raw()`: ```ehtml
{raw(post.bodyHtml)}
``` ## Attributes Attribute values follow normal HTML rules. String literals work. Expression blocks work. ```ehtml
``` `class` accepts an array. Falsy entries drop. The rest join with spaces. Useful for stringing together static and dynamic classes. ```ehtml
``` `style` accepts an object. ```ehtml
``` Identity shortcut: `` is ``. Spread: ``. ## Form Bindings `value`, `checked`, and `group` create two-way bindings. Works on ``, `