# Attributes Typed attributes on a template constructor, reactive expression blocks, and the two-way bindings Elements installs on form controls. ## Where the List Goes **The attribute list `( ... )` goes inside the opening tag of the template, after the tag name and its regular attributes, before the `>`.** That tag is `` for a page or the template's own tag (``) for a component. It is never page content: not after ``, not inside ``, not on a line of its own between elements. ```ehtml Right Sign in ``` Not this: ```ehtml Wrong Sign in ( private form: AuthForm = { email: "", password: "", error: "", mode: "signin" }, ) ``` The wrong form does not report a misplaced list. The compiler reads the `(` as text and the `{` as an expression, so the errors read like a syntax error inside the object: `'}' expected.` and `Unexpected token.` on the declaration's line. If you see those near a `( ... )` list, check that the list sits inside the opening tag before its `>`. ## Declaring Attributes 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 Attributes

{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. ## Initializers Re-run An initializer is live. When anything it reads changes, it runs again and its result replaces the attribute's value, including anything the template wrote to it since. That is what keeps `greeting` above in step with `title`. It also means one initializer should not hold both a value derived from another attribute and state the template owns. Here `live` reads `office`, so switching office rebuilds `live` and the slots the handler stored are gone: ```ehtml Wrong ``` A handler that holds the old object and writes to it after an `await` writes to an object nothing renders any more. Split the two, so the derived part follows `office` and the owned part stays put: ```ehtml Right ``` ## Layout A single short attribute sits on the tag line. ```ehtml Short list ``` More than one, or any attribute with a default value or a long type, goes one per line, so a reader can scan them. The `(` stays on the tag line, each attribute gets a line and a trailing comma, and `)>` closes at the tag's indent. ```ehtml Long list ``` 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 With regular attributes , view: View, private draft: Draft = { title: "" }, ) oninit={() => window.addEventListener("popstate", () => onPopState(view))}> ``` Do not hang the list off the tag name's indent: ```ehtml Wrong ``` 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 Reactive attributes done: {tasks.filter(t => t.done).length} ``` Toggling the checkbox in `` updates the count in `` immediately. **Attributes live on the template's own tag only.** An attribute list on a non-root element (e.g. `
`) is invalid, and so is one in the body (see Where the List Goes). **A default takes the attribute's declared type.** A union attribute takes a literal default directly, and so does a union field inside an object default: ```ehtml Union defaults ``` 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 each union field in it keeps its type. ## Expressions `{ ... }` is a TypeScript expression. Allowed as element children and attribute values. ```ehtml Expressions

{title}

{label}

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

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