@flexzap/form
v1.1.1
Published
All the form components that makes part of the flexzap library
Maintainers
Readme
@flexzap/form
Comprehensive form components and services for Angular applications, providing reusable form controls, validation utilities, and form management solutions. Part of the FlexZap Library ecosystem.
Installation
npm install @flexzap/formPeer Dependencies
This library requires the following peer dependencies:
npm install @angular/common@^21.0.0 @angular/core@^21.0.0Usage
1. Native HTML Validation (Simple)
This approach relies on standard HTML attributes like required, minlength, maxlength, and pattern. The form automatically detects these constraints.
import { Component } from '@angular/core';
import { ZapFormFieldset, ZapFormGroup, ZapFormField, ZapFormInput, ZapFormRow } from '@flexzap/form';
import { ZapButton } from '@flexzap/buttons';
@Component({
imports: [ZapFormFieldset, ZapFormGroup, ZapFormField, ZapFormInput, ZapFormRow, ZapButton],
template: `
<!-- Validation happens on 'blur' (when user leaves the field) -->
<form ZapFormGroup #myForm="ZapForm" [ZapFormValidationStrategy]="'blur'" (ZapFormSubmit)="onSubmit($event)">
<zap-form-fieldset [title]="'User Info'" [description]="'Enter your basic details.'">
<zap-form-row>
<zap-form-field [label]="'Username'">
<input ZapFormInput type="text" name="username" required minlength="3" />
</zap-form-field>
</zap-form-row>
<zap-form-row>
<zap-form-field [label]="'Email'">
<input ZapFormInput type="email" name="email" required />
</zap-form-field>
</zap-form-row>
</zap-form-fieldset>
<zap-button [type]="'submit'" [disabled]="!myForm.isFormValid()"> Submit </zap-button>
</form>
`
})
export class SimpleFormComponent {
onSubmit(data: Record<string, FormDataEntryValue | FormDataEntryValue[]>) {
console.log(JSON.stringify(data, null, 2));
}
}2. Custom Validators (Advanced)
Use ZapFormValidators for more complex logic or when you need custom error messages. Custom validators take precedence over native attributes.
import { Component } from '@angular/core';
import {
ZapFormFieldset,
ZapFormGroup,
ZapFormField,
ZapFormInput,
ZapFormRow,
ZapFormValidators
} from '@flexzap/form';
import { ZapButton } from '@flexzap/buttons';
@Component({
imports: [ZapFormFieldset, ZapFormGroup, ZapFormField, ZapFormInput, ZapFormRow, ZapButton],
template: `
<!-- Validation happens only on 'submit' -->
<form ZapFormGroup #myForm="ZapForm" [ZapFormValidationStrategy]="'submit'" (ZapFormSubmit)="onSubmit($event)">
<zap-form-fieldset [title]="'Security'" [description]="'Setup your security credentials.'">
<zap-form-row>
<zap-form-field
[label]="'Password'"
[validators]="[
validators.required('Password is mandatory'),
validators.minLength(8, 'Password must be at least 8 chars')
]"
>
<input ZapFormInput type="password" name="password" />
</zap-form-field>
</zap-form-row>
<zap-form-row>
<zap-form-field
[label]="'Custom Code'"
[validators]="[validators.pattern(/^[A-Z]{3}-\d{3}$/, 'Format must be ABC-123')]"
>
<input ZapFormInput type="text" name="code" />
</zap-form-field>
</zap-form-row>
</zap-form-fieldset>
<zap-button [type]="'submit'" [disabled]="!myForm.isFormValid()"> Submit </zap-button>
</form>
`
})
export class AdvancedFormComponent {
readonly validators = ZapFormValidators;
onSubmit(data: Record<string, FormDataEntryValue | FormDataEntryValue[]>) {
console.log(JSON.stringify(data, null, 2));
}
}3. Selection Controls
Work with radio buttons and checkboxes using the dedicated components zap-form-radio and zap-form-checkbox.
import { Component } from '@angular/core';
import {
ZapFormFieldset,
ZapFormGroup,
ZapFormField,
ZapFormRadio,
ZapFormCheckbox,
ZapFormRow,
ZapFormInput,
ZapFormValidators
} from '@flexzap/form';
import { ZapButton } from '@flexzap/buttons';
@Component({
imports: [
ZapFormFieldset,
ZapFormGroup,
ZapFormField,
ZapFormRadio,
ZapFormCheckbox,
ZapFormRow,
ZapFormInput,
ZapButton
],
template: `
<form ZapFormGroup #myForm="ZapForm" (ZapFormSubmit)="onSubmit($event)">
<zap-form-fieldset [title]="'Preferences'" [description]="'Choose your settings.'">
<zap-form-row>
<zap-form-field [label]="'Notifications'" [validators]="[validators.required('Please select an option')]">
<zap-form-radio [label]="'Email'">
<input ZapFormInput type="radio" name="notifications" value="email" />
</zap-form-radio>
<zap-form-radio [label]="'SMS'">
<input ZapFormInput type="radio" name="notifications" value="sms" />
</zap-form-radio>
</zap-form-field>
</zap-form-row>
<zap-form-row>
<zap-form-field [label]="'Terms'">
<zap-form-checkbox [label]="'I agree to terms'">
<input ZapFormInput type="checkbox" name="terms" required />
</zap-form-checkbox>
</zap-form-field>
</zap-form-row>
</zap-form-fieldset>
<zap-button [type]="'submit'" [disabled]="!myForm.isFormValid()"> Submit </zap-button>
</form>
`
})
export class SelectionFormComponent {
readonly validators = ZapFormValidators;
onSubmit(data: Record<string, FormDataEntryValue | FormDataEntryValue[]>) {
console.log(JSON.stringify(data, null, 2));
}
}API Reference
ZapFormGroup
A directive that manages the state of a form, including validation and submission.
Inputs
| Property | Type | Default | Description |
| --------------------------- | ------------------------------------------ | ---------- | ------------------------------------------- |
| ZapFormValidationStrategy | 'blur' \| 'change' \| 'submit' \| 'none' | 'submit' | Determines when validation errors are shown |
Outputs
| Event | Type | Description |
| --------------- | ------------------------------------------------------------ | -------------------------------------------- |
| ZapFormSubmit | Record<string, FormDataEntryValue \| FormDataEntryValue[]> | Emitted when the form is valid and submitted |
Properties
| Property | Type | Description |
| ------------- | ------------------------- | ------------------------------------------------------ |
| isFormValid | Signal<boolean> | Computed signal indicating if the entire form is valid |
| onReset | (event?: Event) => void | Method to reset the form state and controls |
ZapFormFieldset
A structural component to group related form fields with a title and optional description.
Inputs
| Property | Type | Default | Description |
| ------------- | -------- | ----------- | ------------------------------ |
| title | string | Required | The main title of the fieldset |
| description | string | undefined | Optional description text |
ZapFormRow
A layout component used to wrap form fields for consistent spacing and alignment.
Usage
<zap-form-row>
<zap-form-field [label]="'Name'">...</zap-form-field>
</zap-form-row>Data Normalization
The ZapFormGroup automatically normalizes form data output to ensure consistency:
- Missing Fields: Fields that are typically excluded from
FormDatawhen unchecked (like radio buttons and checkboxes) are automatically included in the output with an empty string value (""). - Consistency: This ensures that every registered control in your form has a corresponding key in the submitted data object, matching the behavior of empty text inputs.
ZapFormField
A component that wraps a form input and handles label, validation messages, and error states.
Inputs
| Property | Type | Default | Description |
| ------------ | ---------------------- | ----------- | ----------------------------------------------- |
| label | string | Required | The label text for the control |
| message | string | undefined | Helper text to display when there are no errors |
| validators | ZapFormValidatorFn[] | [] | Array of custom validator functions |
ZapFormInput
A directive applied to native input elements to integrate them with the FlexZap form system.
Usage
<input ZapFormInput type="text" name="username" required />ZapFormRadio
A component to style and wrap a native radio input.
Inputs
| Property | Type | Default | Description |
| -------- | -------- | -------- | ---------------------------- |
| label | string | Required | The label text for the radio |
ZapFormCheckbox
A component to style and wrap a native checkbox input.
Inputs
| Property | Type | Default | Description |
| -------- | -------- | -------- | ------------------------------- |
| label | string | Required | The label text for the checkbox |
ZapFormControl
An interface that all form controls (like ZapFormField) implement to participate in the ZapFormGroup validation and state management.
Interface
interface ZapFormControl {
validate(showError?: boolean): boolean;
reset(): void;
readonly controlNames?: () => string[];
}ZapFormValidators
A utility class providing common validator functions.
required(errorMessage?): Checks if value is presentminLength(length, errorMessage?): Checks minimum lengthmaxLength(length, errorMessage?): Checks maximum lengthpattern(regex, errorMessage?): Checks against a regex pattern
Testing
This library uses Jest for unit testing with zoneless Angular configuration.
Running Tests
# From the monorepo root
npm run form:test # Run all unit tests with coverage
npm run form:test:watch # Run tests in watch mode (no coverage)Test Configuration
- Framework: Jest with jest-preset-angular
- Environment: jsdom
- Configuration: Zoneless Angular (mandatory)
- Coverage: Reports generated at
coverage/flexzap/form/
Development
Building the Library
# From the monorepo root
npm run form:build # Build with version bump
ng build @flexzap/form # Build directlyCode Scaffolding
To generate new components within this library:
ng generate component [component-name] --project @flexzap/formPublishing
Build for Publication
# From the monorepo root
npm run form:buildPublish to NPM
cd dist/flexzap/form
npm publish --access publicContributing
This library is part of the FlexZap Library monorepo. Please refer to the main repository for contribution guidelines.
Development Guidelines
- Use standalone components (default behavior)
- Use
input()andoutput()functions instead of decorators - Set
changeDetection: ChangeDetectionStrategy.OnPush - Write comprehensive tests with Jest (zoneless configuration)
- Follow semantic versioning for releases
License
MIT License - see the LICENSE file for details.
Links
- Homepage: https://www.flexzap.dev
- Repository: https://github.com/vitorazevedo/flexzap-library
- Monorepo Documentation: Main README
