# Form

> `<wr-form-item>` — the bare layout wrapper: it stacks a label, a control and an error message, and colours them red when you tell it to. It reads nothing about the control. Its richer sibling `<wr-form-field>` has its own page, and is the one to reach for by default.

Source: https://ngwr.dev/reference/components/form  
Kind: Component, Standalone

## Installation

```angular-ts
import { WrFormItem, WrFormError } from 'ngwr/form';
import { WrInput } from 'ngwr/input';   // the control in the examples below

@Component({ imports: [WrFormItem, WrFormError, WrInput] })
export class MyComponent {}
```

## Which wrapper — item or field?

Both live in `ngwr/form` and both wrap one control. They are not variants of each other, and the choice is not a matter of taste.

```angular-html
<!-- <wr-form-item> — layout only. It knows nothing about the control it
     wraps: no label input, no hint, no id wiring, and `hasError` is a
     boolean YOU compute and pass. Reach for it when the control is not an
     Angular form control at all, or when you want the ngwr spacing and
     nothing else. -->
<wr-form-item [hasError]="invalid()">
  <label for="email">Email</label>
  <input id="email" wrInput [(ngModel)]="email" />
  @if (invalid()) { <wr-form-error>Enter a valid email.</wr-form-error> }
</wr-form-item>

<!-- <wr-form-field> — the default choice. It reads the projected control's
     NgControl, so it decides for itself when to show an error (touched or
     dirty), generates the <label for> target, wires aria-describedby, and
     renders the validator's message with no <wr-form-error> at all.
     Its own page has the full API. -->
<wr-form-field label="Email" hint="We'll never share it." required>
  <input wrInput formControlName="email" />
</wr-form-field>
```

## Basic usage

```html
<wr-form-item>
  <label>Email</label>
  <input wrInput type="email" [(ngModel)]="email" />
</wr-form-item>
```

## With error

Toggle hasError to color label/input red and reveal the error message.

```html
<wr-form-item [hasError]="invalid()">
  <label>Email</label>
  <input wrInput type="email" [(ngModel)]="email" />
  <wr-form-error>Please enter a valid email.</wr-form-error>
</wr-form-item>
```

## Form Item API

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `hasError` | Apply error coloring to label + input. | `boolean` | `false` |

## Form Error API

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `key` | Validator key this message corresponds to (e.g. `'required'`). Optional — without a key the message always renders, which is the plain inline-error usage inside `<wr-form-item>`. | `string` | — |

## \<wr-form-field> API — for reference

The other wrapper's API, listed here because both ship from the one `ngwr/form` entry point. It is NOT the component this page's Installation block imports: to use it, import `WrFormField` and read its own page, which has the examples.

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `label` | Label text shown above the control. | `string` | `''` |
| `hint` | Hint text shown below the control. Hidden when an error is visible. | `string` | `''` |
| `required` | Show a `*` next to the label. | `boolean` | `false` |
| `optional` | Show an "optional" marker next to the label — the word comes from `optionalLabel`. Mutually exclusive with `required`. | `boolean` | `false` |
| `optionalLabel` | Word inside the optional marker's parentheses. Falls back to `form.optional`, then `'optional'`. The parentheses are the template's, so no locale has to repeat punctuation. | `string \| null` | `null` |
| `controlId` | Force a specific id on the label's `for` attribute. Auto-generated otherwise, and adopted by the projected `wrInput` unless that element already carries an `id` of its own. | `string` | ```wr-form-field-${++uid}``` |
| `autoErrors` | Render a catalog message for any error the markup does not already answer. On by default: a field with no `<wr-form-error>` at all is the common case, and an empty error block helps nobody. Turn it off for a field whose copy is entirely hand-written. | `boolean` | `true` |

## See also

- [wr-form-field](https://ngwr.dev/reference/components/form-field) — The richer wrapper, and the default choice — label, hint, required marker and validation messages resolved from the control itself.
- [wrInput](https://ngwr.dev/reference/components/input) — The control both wrappers are built around. `input[wrInput], textarea[wrInput]` — no `wrTextarea`.
