Primitives
Please include any middle names, no matter how ridiculous. This field is required.import { Component } from "@angular/core";
import {
FormControl,
FormGroup,
ReactiveFormsModule,
Validators,
} from "@angular/forms";
import {
NgpDescription,
NgpError,
NgpFormControl,
NgpFormField,
NgpLabel,
} from "ng-primitives/form-field";
@Component({
selector: "app-form-field",
imports: [
NgpFormField,
NgpLabel,
NgpError,
NgpDescription,
NgpFormControl,
ReactiveFormsModule,
],
template: `
<div [formGroup]="formGroup" ngpFormField>
<label ngpLabel>Full Name</label>
<p ngpDescription>
Please include any middle names, no matter how ridiculous.
</p>
<input
ngpFormControl
type="text"
placeholder="Enter your full name"
formControlName="fullName"
/>
<p ngpError ngpErrorValidator="required">This field is required.</p>
</div>
`,
styles: `
:host {
display: contents;
}
[ngpFormField] {
display: flex;
flex-direction: column;
gap: 6px;
width: 90%;
}
[ngpFormControl] {
height: 36px;
width: 100%;
border-radius: 8px;
padding: 0 16px;
border: none;
box-shadow: var(--ngp-input-shadow);
outline: none;
}
[ngpFormControl]:focus {
outline: 2px solid var(--ngp-focus-ring);
outline-offset: 2px;
}
[ngpFormControl]::placeholder {
color: var(--ngp-text-placeholder);
}
[ngpLabel] {
color: var(--ngp-text-primary);
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
margin: 0;
}
[ngpDescription] {
color: var(--ngp-text-secondary);
font-size: 0.75rem;
line-height: 1rem;
margin: 0 0 4px;
}
[ngpError] {
display: none;
color: var(--ngp-text-red);
font-size: 0.75rem;
line-height: 1rem;
margin: 0;
}
[ngpError][data-validator="fail"][data-dirty] {
display: block;
}
`,
})
export default class FormFieldExample {
/** The Angular Form Group */
readonly formGroup = new FormGroup({
fullName: new FormControl("", Validators.required),
});
}
Import the FormField primitives from ng-primitives/form-field
.
import {
NgpFormField,
NgpLabel,
NgpDescription,
NgpError,
NgpFormControl,
} from 'ng-primitives/form-field';
Assemble the form-field directives in your template.
<div ngpFormField>
<label ngpLabel>Label</label>
<!-- Typically ngpFormControl would not be used directly, but a primitive like ngpInput would be used instead -->
<input ngpFormControl />
<p ngpDescription>Description</p>
<p ngpError ngpErrorValidator="required">Error</p>
</div>
Create a reusable component that uses the NgpFormField
directive.
import { Component } from '@angular/core';
import { FormField } from './form-field';
@Component({
selector: 'app-root',
imports: [FormField],
template: `
<app-form-field>
<!-- Add label and form control here -->
<label>Username</label>
<input type="text" placeholder="Enter your username" />
</app-form-field>
`,
})
export default class App {}
Generate a reusable form-field component using the Angular CLI.
ng g ng-primitives:primitive form-field
path
: The path at which to create the component file.prefix
: The prefix to apply to the generated component selector.componentSuffix
: The suffix to apply to the generated component class name.fileSuffix
: The suffix to apply to the generated component file name. Defaults to component
.exampleStyles
: Whether to include example styles in the generated component file. Defaults to true
.The following directives are available to import from the ng-primitives/form-field
package:
The `NgpFormField` directive is a container for form field elements. Any labels, form controls, or descriptions should be placed within this directive.[ngpFormField]
ngpFormField
Attribute | Description |
---|---|
data-invalid |
Applied when the form control is invalid. |
data-valid |
Applied when the form control is valid. |
data-touched |
Applied when the form control is touched. |
data-pristine |
Applied when the form control is pristine. |
data-dirty |
Applied when the form control is dirty. |
data-pending |
Applied when the form control is pending. |
data-disabled |
Applied when the form control is disabled. |
The `NgpLabel` directive is used to mark a label element within a form field. Preferably, there should use an HTML `<label>` element.[ngpLabel]
ngpLabel
Attribute | Description | Value |
---|---|---|
data-invalid |
Applied when the form control is invalid. | |
data-valid |
Applied when the form control is valid. | |
data-touched |
Applied when the form control is touched. | |
data-pristine |
Applied when the form control is pristine. | |
data-dirty |
Applied when the form control is dirty. | |
data-pending |
Applied when the form control is pending. | |
data-disabled |
Applied when the form control is disabled. |
The `NgpDescription` directive is used to mark a description element within a form field. There may be multiple descriptions associated with a form control.[ngpDescription]
ngpDescription
Attribute | Description | Value |
---|---|---|
data-invalid |
Applied when the form control is invalid. | |
data-valid |
Applied when the form control is valid. | |
data-touched |
Applied when the form control is touched. | |
data-pristine |
Applied when the form control is pristine. | |
data-dirty |
Applied when the form control is dirty. | |
data-pending |
Applied when the form control is pending. | |
data-disabled |
Applied when the form control is disabled. |
The `NgpError` directive is used to mark an error message element within a form field. There may be multiple error messages associated with a form control. The validator associated with the error message.
[ngpError]
ngpError
Attribute | Description | Value |
---|---|---|
data-validator |
Whether the validator specified in ngpErrorValidator is failing. |
fail | pass |
data-invalid |
Applied when the form control is invalid. | - |
data-valid |
Applied when the form control is valid. | - |
data-touched |
Applied when the form control is touched. | - |
data-pristine |
Applied when the form control is pristine. | - |
data-dirty |
Applied when the form control is dirty. | - |
data-pending |
Applied when the form control is pending. | - |
data-disabled |
Applied when the form control is disabled. | - |
Typically this primitive would be not be used directly, but instead a more specific form control primitive would be used (e.g. `ngpInput`). All of our form control primitives use `ngpFormControl` internally so they will have the same accessibility features as described below.
The `NgpFormControl` directive is used to mark a form control element within a form field. This element will have an `aria-labelledby` attribute set to the ID of the label element within the form field and an `aria-describedby` attribute set to the ID of the description elements within the form field. Whether the form control is disabled by a parent.
[ngpFormControl]
ngpFormControl
Attribute | Description | Value |
---|---|---|
data-invalid |
Applied when the form control is invalid. | |
data-valid |
Applied when the form control is valid. | |
data-touched |
Applied when the form control is touched. | |
data-pristine |
Applied when the form control is pristine. | |
data-dirty |
Applied when the form control is dirty. | |
data-pending |
Applied when the form control is pending. | |
data-disabled |
Applied when the form control is disabled. |
The label and description elements should be associated with the form control using the aria-labelledby
and aria-describedby
attributes, respectively. This will ensure that screen readers can provide the necessary context to users.
Copyright © 2025 Angular Primitives