# Input

> Attribute directive applied to a native `<input>` (or `<textarea>`). Because the styling lives on the real input, third-party directives like `ngx-mask`, custom validators, and `[(ngModel)]` compose naturally on the same element.

Source: https://ngwr.dev/reference/components/input  
Kind: Directive, a11y

## Installation

```angular-ts
import {
  WrInput,
  WrInputGroup,
  WrInputPrefix,
  WrInputSuffix,
  WrPasswordToggle
} from 'ngwr/input';
import { FormsModule } from '@angular/forms';

@Component({
  imports: [
    WrInput,
    WrInputGroup,
    WrInputPrefix,
    WrInputSuffix,
    WrPasswordToggle,
    FormsModule,
  ],
})
export class MyComponent {
  text = signal('');
}
```

## Basic usage

```html
<input wrInput placeholder="Type here…" [(ngModel)]="text" />
```

## Types

Set any native `type` — text, number, email, search, tel, url, password.

```html
<input wrInput type="email" placeholder="you@example.com" />
<input wrInput type="number" placeholder="0" />
<input wrInput type="search" placeholder="Search" />
```

## Prefix & suffix

Wrap in `<wr-input-group>` and mark sibling elements with `[wrInputPrefix]` / `[wrInputSuffix]`. The group owns the border and focus ring (via `:focus-within`).

```html
<wr-input-group>
  <span wrInputPrefix>$</span>
  <input wrInput type="number" [(ngModel)]="amount" />
  <span wrInputSuffix>USD</span>
</wr-input-group>
```

## Rounded

```html
<input wrInput rounded placeholder="Rounded" />
```

## Password reveal

`<wr-password-toggle>` flips its linked input's `type` attribute between `password` and `text`. Use a template ref to wire them up.

```html
<wr-input-group>
  <input wrInput type="password" [(ngModel)]="password" #pwInput />
  <wr-password-toggle [for]="pwInput" />
</wr-input-group>
```

## Input masking — with ngx-mask

ngwr does not ship a mask directive of its own, and deliberately does not wrap one either — a mask is input plumbing, not a look, so blessing the ecosystem's standard beats owning a second copy of it. `ngx-mask` is that standard: battle-tested, signal-compatible, MIT, and about 18 KB once minified and gzipped. Because `[wrInput]` is just a directive on the real `<input>`, it plugs in on the same element with zero ceremony.

### Setup

```angular-ts
// 1. Install ngx-mask as a peer dependency:
//    pnpm add ngx-mask

// 2. Provide it at bootstrap once (pass overrides for global defaults):
import { provideEnvironmentNgxMask } from 'ngx-mask';

bootstrapApplication(AppComponent, {
  providers: [
    provideEnvironmentNgxMask({
      thousandSeparator: ',',
      decimalMarker: '.',
    }),
  ],
});

// 3. Import the directive in any standalone component:
import { NgxMaskDirective } from 'ngx-mask';

@Component({
  imports: [NgxMaskDirective, WrInput, FormsModule],
})
export class MyForm {}
```

#### Common masks

```html
<!-- Phone (US-style) -->
<input wrInput mask="(000) 000-0000" placeholder="(555) 555-5555" [(ngModel)]="phone" />

<!-- Credit card -->
<input wrInput mask="0000 0000 0000 0000" placeholder="4242 4242 4242 4242" [(ngModel)]="card" />

<!-- Expiry MM/YY -->
<input wrInput mask="00/00" placeholder="12/29" [(ngModel)]="expiry" />

<!-- CVC (3 digits) -->
<input wrInput mask="000" placeholder="123" [(ngModel)]="cvc" />

<!-- Date DD/MM/YYYY -->
<input wrInput mask="00/00/0000" placeholder="31/12/2026" [(ngModel)]="date" />

<!-- Money: separator with two-decimal precision -->
<wr-input-group>
  <span wrInputPrefix>$</span>
  <input wrInput mask="separator.2" [(ngModel)]="money" placeholder="1,234.56" />
</wr-input-group>
```

Full token reference (custom patterns, dynamic masks, locale config) — see [the ngx-mask docs](https://jsdaddy.github.io/ngx-mask).

## Disabled

```html
<input wrInput placeholder="Disabled" disabled />
```

## In a form, this is the one that behaves natively

`[wrInput]` styles a real `<input>`, so its form semantics are Angular's own — and they differ from every ngwr **component** in the catalog. Worth knowing before you mix the two in one `FormGroup`.

A native `<input>` binds through the `DefaultValueAccessor` Angular ships. Every ngwr value component — `<wr-select>`, `<wr-input-number>`, `<wr-checkbox>` and the rest — binds through [Angular 22's forms bridge](https://ngwr.dev/guides/forms) instead, because the library ships no `ControlValueAccessor` at all. Two consequences show up as soon as both are in the same form. **`updateOn: 'blur'` and `'submit'` hold here and are ignored by the components**, and **a `{ emitEvent: false }` write repaints this field and not them.** Neither is a bug in either half; the guide explains both and what to do about them.

## [wrInput] directive

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `wrInput` | Selector. Applies NGWR input styling to a native `<input>` or `<textarea>`. | `attribute` | `—` |
| `size` | Control size. | `'sm' \| 'md' \| 'lg' \| null` | `'md'` |
| `rounded` | Pill-shaped corners. | `boolean \| null` | `false` |

## \<wr-input-group>

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `wr-input-group` | Wrapper for the input + prefix/suffix/toggle siblings. | `component` | `—` |
| `rounded` | Pill-shaped corners. | `boolean \| null` | `false` |

## Prefix & suffix directives

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `[wrInputPrefix]` | Marks an element as the left affix. | `attribute` | `—` |
| `[wrInputSuffix]` | Marks an element as the right affix. | `attribute` | `—` |

## \<wr-password-toggle>

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `for`required | The linked password `<input>` reference. | `HTMLInputElement` | — |
| `showLabel` | Accessible name while the password is hidden — the button is icon-only. Falls back to the input.showPassword catalog key. | `string \| null` | `null` |
| `hideLabel` | Accessible name while the password is revealed. Falls back to the input.hidePassword catalog key. | `string \| null` | `null` |

## CSS variables

Custom properties `ngwr/input` publishes. Each default below is declared on the component's own selector, so a `:root` override is shadowed by it — set them on that selector, on a wrapper you scope yourself, or inline on the element. Unlike the BEM class names, these are the supported way to restyle the component.

| Variable | Default | Declared on |
| --- | --- | --- |
| `--wr-input-bg` | `var(--wr-color-surface)` | `.wr-input` +1 variant override |
| `--wr-input-border` | `var(--wr-color-outline)` | `.wr-input` +2 variant overrides |
| `--wr-input-color` | `var(--wr-color-on-surface)` | `.wr-input` +1 variant override |
| `--wr-input-font-size` | `var(--wr-control-font-size-md)` | `.wr-input` +2 variant overrides |
| `--wr-input-group-affix` | `var(--wr-color-on-surface-muted)` | `.wr-input-group` |
| `--wr-input-group-bg` | `var(--wr-color-surface)` | `.wr-input-group` +1 variant override |
| `--wr-input-group-border` | `var(--wr-color-outline)` | `.wr-input-group` +1 variant override |
| `--wr-input-group-padding-x` | `0.75rem` | `.wr-input-group` +1 variant override |
| `--wr-input-group-radius` | `var(--wr-control-radius-md)` | `.wr-input-group` +1 variant override |
| `--wr-input-group-ring` | `transparent` | `.wr-input-group` +1 variant override |
| `--wr-input-line-height` | `var(--wr-control-line-height-md)` | `.wr-input` +2 variant overrides |
| `--wr-input-padding-x` | `var(--wr-control-padding-x-md)` | `.wr-input` +3 variant overrides |
| `--wr-input-padding-y` | `var(--wr-control-padding-y-md)` | `.wr-input` +2 variant overrides |
| `--wr-input-placeholder` | `rgba(var(--wr-color-on-surface-muted-rgb), 0.7)` | `.wr-input` |
| `--wr-input-radius` | `var(--wr-control-radius-md)` | `.wr-input` +3 variant overrides |
| `--wr-input-ring` | `transparent` | `.wr-input` +2 variant overrides |
