Form Field
Display a form field to handle errors and hints.
import { Component } from '@angular/core';
import { HlmFormFieldModule } from '@spartan-ng/ui-formfield-helm';
import { HlmInputDirective } from '@spartan-ng/ui-input-helm';
@Component({
selector: 'spartan-form-field-preview',
standalone: true,
imports: [HlmInputDirective, HlmFormFieldModule],
template: `
<hlm-form-field>
<input class="w-80" hlmInput type="email" placeholder="Email" />
<hlm-hint>This is your email address.</hlm-hint>
</hlm-form-field>
`,
})
export class FormFieldPreviewComponent {}
Installation
npx nx g @spartan-ng/cli:ui formfield
ng g @spartan-ng/cli:ui formfield
Usage
import { HlmFormFieldModule } from '@spartan-ng/ui-formfield-helm';
import { HlmInputDirective } from '@spartan-ng/ui-input-helm';
<hlm-form-field>
<input class="w-80" hlmInput type="email" placeholder="Email" />
<hlm-hint>This is your email address.</hlm-hint>
</hlm-form-field>
Examples
Default
import { Component } from '@angular/core';
import { HlmFormFieldModule } from '@spartan-ng/ui-formfield-helm';
import { HlmInputDirective } from '@spartan-ng/ui-input-helm';
@Component({
selector: 'spartan-form-field-preview',
standalone: true,
imports: [HlmInputDirective, HlmFormFieldModule],
template: `
<hlm-form-field>
<input class="w-80" hlmInput type="email" placeholder="Email" />
<hlm-hint>This is your email address.</hlm-hint>
</hlm-form-field>
`,
})
export class FormFieldPreviewComponent {}
Error
import { Component, OnInit } from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { HlmFormFieldModule } from '@spartan-ng/ui-formfield-helm';
import { HlmInputDirective } from '@spartan-ng/ui-input-helm';
@Component({
standalone: true,
selector: 'spartan-form-field-error',
imports: [ReactiveFormsModule, HlmFormFieldModule, HlmInputDirective],
template: `
<hlm-form-field>
<input aria-label="Your Name" class="w-80" [formControl]="name" hlmInput type="text" placeholder="Your Name" />
<hlm-error>Your name is required</hlm-error>
</hlm-form-field>
`,
})
export class FormFieldErrorPreviewComponent implements OnInit {
name = new FormControl('', Validators.required);
ngOnInit(): void {
this.name.markAsTouched();
}
}
With Form
import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { HlmButtonModule } from '@spartan-ng/ui-button-helm';
import { HlmFormFieldModule } from '@spartan-ng/ui-formfield-helm';
import { HlmInputDirective } from '@spartan-ng/ui-input-helm';
import { BrnSelectImports } from '@spartan-ng/brain/select';
import { HlmSelectImports, HlmSelectModule } from '@spartan-ng/ui-select-helm';
@Component({
standalone: true,
selector: 'spartan-form-field-form',
imports: [
ReactiveFormsModule,
HlmFormFieldModule,
HlmSelectModule,
HlmInputDirective,
HlmSelectImports,
BrnSelectImports,
HlmButtonModule,
],
template: `
<form [formGroup]="form" class="space-y-6">
<hlm-form-field>
<input
aria-label="Your Name"
formControlName="name"
class="w-80"
hlmInput
type="text"
placeholder="Your Name"
/>
<hlm-error>Your name is required</hlm-error>
</hlm-form-field>
<hlm-form-field>
<brn-select class="inline-block" placeholder="Select some fruit" formControlName="fruit">
<hlm-select-trigger class="w-80">
<hlm-select-value />
</hlm-select-trigger>
<hlm-select-content>
<hlm-select-label>Fruits</hlm-select-label>
@for (option of options; track option.value) {
<hlm-option [value]="option.value">{{ option.label }}</hlm-option>
}
</hlm-select-content>
</brn-select>
<hlm-error>The fruit is required</hlm-error>
</hlm-form-field>
<button type="submit" hlmBtn>Submit</button>
</form>
`,
})
export class FormFieldFormPreviewComponent {
private _formBuilder = inject(FormBuilder);
form = this._formBuilder.group({
name: ['', Validators.required],
fruit: ['', Validators.required],
});
options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'blueberry', label: 'Blueberry' },
{ value: 'grapes', label: 'Grapes' },
{ value: 'pineapple', label: 'Pineapple' },
];
}
Changing when error messages are shown
By default, these error messages are shown when the control is invalid and the user has interacted with (touched) the element or the parent form has been submitted. If you wish to override this behavior (e.g. to show the error as soon as the invalid control is dirty or when a parent form group is invalid), you can use the ErrorStateMatcher
provider.
For convenience, ShowOnDirtyErrorStateMatcher
is available in order to globally cause input errors to show when the input is dirty and invalid
providers: [
{ provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher }
]
import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { HlmButtonModule } from '@spartan-ng/ui-button-helm';
import { ErrorStateMatcher, ShowOnDirtyErrorStateMatcher } from '@spartan-ng/brain/forms';
import { HlmFormFieldModule } from '@spartan-ng/ui-formfield-helm';
import { HlmInputDirective } from '@spartan-ng/ui-input-helm';
import { BrnSelectImports } from '@spartan-ng/brain/select';
import { HlmSelectImports, HlmSelectModule } from '@spartan-ng/ui-select-helm';
@Component({
standalone: true,
selector: 'spartan-form-field-form',
imports: [
ReactiveFormsModule,
HlmFormFieldModule,
HlmSelectModule,
HlmInputDirective,
HlmSelectImports,
BrnSelectImports,
HlmButtonModule,
],
template: `
<form [formGroup]="form" class="space-y-6">
<hlm-form-field>
<input
aria-label="Your Name"
formControlName="name"
class="w-80"
hlmInput
type="text"
placeholder="Your Name"
/>
<hlm-error>Your name is required</hlm-error>
</hlm-form-field>
<hlm-form-field>
<brn-select class="inline-block" placeholder="Select some fruit" formControlName="fruit">
<hlm-select-trigger class="w-80">
<hlm-select-value />
</hlm-select-trigger>
<hlm-select-content>
<hlm-select-label>Fruits</hlm-select-label>
@for (option of options; track option.value) {
<hlm-option [value]="option.value">{{ option.label }}</hlm-option>
}
</hlm-select-content>
</brn-select>
<hlm-error>The fruit is required</hlm-error>
</hlm-form-field>
<button type="submit" hlmBtn>Submit</button>
</form>
`,
providers: [{ provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher }],
})
export class FormFieldFormWithDirtyPreviewComponent {
private _formBuilder = inject(FormBuilder);
form = this._formBuilder.group({
name: ['', Validators.required],
fruit: ['', Validators.required],
});
options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'blueberry', label: 'Blueberry' },
{ value: 'grapes', label: 'Grapes' },
{ value: 'pineapple', label: 'Pineapple' },
];
}