import { Component } from '@angular/core';
import { WrButton } from 'ngwr/button';
import { WrFormError, WrFormField } from 'ngwr/form';
import { WrInput } from 'ngwr/input';
@Component({ imports: [WrButton, WrFormError, WrFormField, WrInput] })
export class MyComponent {}Form Field
Wraps a form control with a label, a hint and its error messages.
Installation
Import the class, and @use the entry point in your global styles: without it the component renders unstyled.
Basic usage
Add one <wr-form-error key> per validator; errors show once the control is touched or dirty.
<wr-form-field label="Email" hint="We'll never share it." required>
<input wrInput [formControl]="email" type="email" />
<wr-form-error key="required">Email is required.</wr-form-error>
<wr-form-error key="email">That isn't a valid email.</wr-form-error>
</wr-form-field>Messages without markup
Without <wr-form-error>, the field shows the rule's { message }, else validation.<key> from your i18n catalog, else nothing.
<!-- Messages come from validation.required, .minlength and .min in your catalog. -->
<wr-form-field label="Handle" required>
<input wrInput formControlName="handle" />
</wr-form-field>
<wr-form-field label="Age">
<input wrInput formControlName="age" type="number" />
</wr-form-field>A message on the validator
Signal Forms rules take { message }. A custom validator puts a message string on its error.
import { Component, signal } from '@angular/core';
import { FormField, email, form, required } from '@angular/forms/signals';
import { WrFormField } from 'ngwr/form';
import { WrInput } from 'ngwr/input';
@Component({
imports: [FormField, WrFormField, WrInput],
template: `
<wr-form-field label="Work email" required>
<input wrInput type="email" [formField]="signup.email" />
</wr-form-field>
`,
})
export class Signup {
private readonly model = signal({ email: '' });
protected readonly signup = form(this.model, path => {
required(path.email, { message: 'Enter your work email.' });
email(path.email, { message: 'That is not an email address.' });
});
}A message in your catalog
A validation.<key> entry covers that error on every field; minLength and maxLength read the minlength and maxlength keys.
provideWrI18nStaticLoader({
en: {
validation: {
required: 'This field is required.',
// Filled from the error payload: { requiredLength, actualLength }.
minlength: 'Minimum length is {{requiredLength}}.',
min: 'Enter {{min}} or more.',
},
},
ru: {
validation: {
required: 'Обязательное поле.',
minlength: 'Не короче {{requiredLength}} символов.',
min: 'Не меньше {{min}}.',
},
},
}),A message in the markup
<wr-form-error key> wins for its key on that field. Other keys still resolve.
<wr-form-field label="Handle" required>
<input wrInput formControlName="handle" />
<!-- Only for required; minlength still resolves. -->
<wr-form-error key="required">Pick a handle.</wr-form-error>
</wr-form-field>Optional marker
optional marks a field users can skip.
<wr-form-field label="Bio" optional hint="Up to 140 characters.">
<input wrInput [formControl]="bio" placeholder="A short tagline" />
</wr-form-field>Required marker
required only draws the asterisk. It adds no validator, and a validator does not set it: write both.
<!-- Validators.required on the control, required on the field. -->
<wr-form-field label="Email" required>
<input wrInput formControlName="email" type="email" />
</wr-form-field>
<!-- Or read it off the control; requiredValidator is Validators.required. -->
<wr-form-field label="Email" [required]="form.controls.email.hasValidator(requiredValidator)">
<input wrInput formControlName="email" type="email" />
</wr-form-field>API
| Name | Description | Type | Default |
|---|---|---|---|
label | Label text shown above the projected control. | string | '' |
optionalLabel | Word inside the optional marker. Defaults to the form.optional catalog key. | string | null | null |
autoErrors | Show a message for each error no <wr-form-error> claims. Turn off to write every message by hand. | boolean | true |
hint | Subtext under the control. Hidden when an error is visible. | string | '' |
required | Show a red * next to the label. | boolean | false |
optional | Show (optional) next to the label. Ignored if required is on. | boolean | false |
controlId | Set the <label for> target manually. Auto-generated otherwise. | string | auto |
<wr-form-error> | One message per validator key. Shows when the control is touched or dirty and has that error. | component | — |