kits-ngx-validation
v0.0.1
Published
A reusable, scalable and extensible validation library for Angular reactive forms.
Downloads
140
Maintainers
Readme
kits-ngx-validation
Reusable and scalable validation infrastructure for Angular Reactive Forms.
kits-ngx-validation provides a centralized validation system for Angular applications, including validation state management, validation messages, visibility strategies, localization, and reusable form-field presentation.
Designed for applications ranging from small projects to large enterprise and ERP systems.
Features
- Angular Reactive Forms integration
- Angular 17+ support
- Signal-based validation state
- Automatic validation error handling
- Built-in Angular validator messages
- Arabic and English messages
- Dynamic message parameters
- Configurable validation visibility
- Form submission tracking
- Custom validation messages
- Custom message resolver support
- Reusable form-field component
- Standalone Angular APIs
- No UI framework dependency
- Tree-shakable
Requirements
- Angular 17+
- Angular Reactive Forms
- TypeScript version compatible with your Angular version
Supported Angular versions:
| Angular | Support | | -------------- | ----------------- | | 17 | ✅ | | 18 | ✅ | | 19 | ✅ | | 20 | ✅ | | Newer versions | ✅ When compatible |
Installation
Install the package using npm:
npm install kits-ngx-validationQuick Start
kits-ngx-validation works with Angular Reactive Forms.
1. Create your form
import { Component, inject } from '@angular/core';
import {
FormBuilder,
ReactiveFormsModule,
Validators
} from '@angular/forms';
@Component({
selector: 'app-user-form',
standalone: true,
imports: [
ReactiveFormsModule
],
templateUrl: './user-form.component.html'
})
export class UserFormComponent {
private readonly fb = inject(FormBuilder);
readonly form = this.fb.group({
name: [
'',
[
Validators.required,
Validators.minLength(3)
]
],
email: [
'',
[
Validators.required,
Validators.email
]
]
});
submit(): void {
if (this.form.invalid) {
return;
}
console.log(this.form.value);
}
}2. Add the validation components
Import:
import {
KitsFormFieldComponent,
ValidationFormDirective
} from 'kits-ngx-validation';Then add them to your component:
@Component({
selector: 'app-user-form',
standalone: true,
imports: [
ReactiveFormsModule,
KitsFormFieldComponent,
ValidationFormDirective
],
templateUrl: './user-form.component.html'
})
export class UserFormComponent {}3. Use them in your template
<form
kitsValidationForm
[formGroup]="form"
(ngSubmit)="submit()">
<kits-form-field>
<input
type="text"
formControlName="name"
placeholder="Name"
/>
</kits-form-field>
<kits-form-field>
<input
type="email"
formControlName="email"
placeholder="Email"
/>
</kits-form-field>
<button type="submit">
Submit
</button>
</form>That's it.
The library automatically reads Angular validation errors and displays the corresponding validation messages.
How It Works
The validation flow is intentionally simple:
Angular FormControl
↓
Validation State
↓
Validation Errors
↓
Visibility Strategy
↓
Message Resolution
↓
Validation MessageYou continue using Angular Reactive Forms normally.
The library handles the validation presentation layer around them.
Validation Form
Add:
<form
kitsValidationForm
[formGroup]="form"
(ngSubmit)="submit()">
</form>kitsValidationForm tracks the form submission state.
This allows validation messages to be displayed after submission without manually maintaining a submitted variable in every component.
For example:
submit(): void {
if (this.form.invalid) {
return;
}
// Submit the form
}Form Field
Use kits-form-field around an Angular form control:
<kits-form-field>
<input
formControlName="email"
type="email"
/>
</kits-form-field>The component connects the contained Angular control to the validation system and renders its validation messages.
This removes repetitive validation markup from application forms.
Angular Validators
The library works with standard Angular validators.
For example:
this.form = this.fb.group({
username: [
'',
[
Validators.required,
Validators.minLength(3)
]
],
email: [
'',
[
Validators.required,
Validators.email
]
],
age: [
null,
[
Validators.required,
Validators.min(18),
Validators.max(100)
]
]
});Supported Angular validation errors include:
required
requiredTrue
email
min
max
minlength
maxlength
patternThe library automatically extracts the validation error code and its parameters.
Validation Messages
The package includes default messages for common Angular validators.
Arabic
required
هذا الحقل مطلوب
email
يرجى إدخال بريد إلكتروني صحيح
minlength
يجب أن يحتوي هذا الحقل على {{requiredLength}} أحرف على الأقل
maxlength
يجب ألا يتجاوز هذا الحقل {{requiredLength}} أحرف
min
يجب أن تكون القيمة أكبر من أو تساوي {{min}}
max
يجب أن تكون القيمة أقل من أو تساوي {{max}}
pattern
صيغة القيمة غير صحيحة
requiredTrue
يجب الموافقة على هذا الحقلEnglish
required
This field is required
email
Please enter a valid email address
minlength
This field must contain at least {{requiredLength}} characters
maxlength
This field must not exceed {{requiredLength}} characters
min
Value must be greater than or equal to {{min}}
max
Value must be less than or equal to {{max}}
pattern
The value format is invalid
requiredTrue
This field must be acceptedDynamic Message Parameters
Validation messages support dynamic parameters.
For example:
Validators.minLength(5)provides information such as:
requiredLength
actualLengthA message such as:
This field must contain at least {{requiredLength}} characterswill be resolved dynamically.
For example:
This field must contain at least 5 charactersParameters use the following syntax:
{{parameterName}}Language
The library supports:
'ar'
'en'The default language is Arabic.
You can configure English globally.
import {
KITS_VALIDATION_CONFIG
} from 'kits-ngx-validation';
export const appConfig: ApplicationConfig = {
providers: [
{
provide: KITS_VALIDATION_CONFIG,
useValue: {
language: 'en',
visibility: 'touched-or-submitted'
}
}
]
};Validation Visibility
Validation messages are not required to appear immediately.
The library provides configurable visibility strategies.
type ValidationVisibility =
| 'touched'
| 'dirty'
| 'submitted'
| 'touched-or-submitted'
| 'dirty-or-submitted'
| 'always'
| 'never';touched
Display validation messages after the control has been touched.
visibility: 'touched'dirty
Display validation messages after the control value changes.
visibility: 'dirty'submitted
Display validation messages after the form is submitted.
visibility: 'submitted'touched-or-submitted
Display messages when the control is touched or the form is submitted.
visibility: 'touched-or-submitted'This is the default strategy.
dirty-or-submitted
Display messages when the control is dirty or the form is submitted.
visibility: 'dirty-or-submitted'always
Display messages whenever the control is invalid.
visibility: 'always'never
Hide validation messages.
visibility: 'never'Custom Messages
You can override default validation messages.
import {
KITS_VALIDATION_CONFIG
} from 'kits-ngx-validation';
export const appConfig: ApplicationConfig = {
providers: [
{
provide: KITS_VALIDATION_CONFIG,
useValue: {
language: 'en',
visibility: 'touched-or-submitted',
messages: {
required: 'Please enter a value',
email: 'Please enter a valid email address'
}
}
}
]
};The configured message takes precedence over the built-in message.
Custom Message Resolver
For applications with a centralized translation system, you can provide a custom message resolver.
import {
KITS_VALIDATION_CONFIG
} from 'kits-ngx-validation';
export const appConfig: ApplicationConfig = {
providers: [
{
provide: KITS_VALIDATION_CONFIG,
useValue: {
language: 'en',
visibility: 'touched-or-submitted',
messageResolver: (
code,
params,
language
) => {
// Resolve the message
// using your application's
// translation system.
return undefined;
}
}
}
]
};This allows kits-ngx-validation to integrate with an existing localization infrastructure without coupling the library to a specific translation package.
Custom Validators
You can continue using Angular's standard ValidatorFn contract.
Example:
import {
AbstractControl,
ValidationErrors
} from '@angular/forms';
export function positiveNumberValidator(
control: AbstractControl
): ValidationErrors | null {
const value = control.value;
if (value === null || value === '') {
return null;
}
return Number(value) > 0
? null
: {
positiveNumber: true
};
}Use it normally:
this.form = this.fb.group({
amount: [
null,
[
Validators.required,
positiveNumberValidator
]
]
});The custom error code becomes:
positiveNumberYou can then provide a corresponding custom validation message through the configuration.
Validation State
The library provides a centralized reactive validation state.
The state contains:
interface ValidationState {
readonly invalid: boolean;
readonly valid: boolean;
readonly pending: boolean;
readonly touched: boolean;
readonly untouched: boolean;
readonly dirty: boolean;
readonly pristine: boolean;
readonly disabled: boolean;
readonly enabled: boolean;
readonly submitted: boolean;
readonly errors: readonly ValidationError[];
}The state is built using Angular Signals.
This allows validation UI to react automatically when form state changes.
Validation Errors
Validation errors are normalized into:
interface ValidationError {
readonly code: ValidationErrorCode;
readonly messageKey: string;
readonly params?: ValidationMessageParams;
readonly source: ValidationSource;
readonly priority: number;
}Example:
code:
required
messageKey:
validation.required
source:
angular
priority:
100Validation Priority
Validation errors have a priority system.
The built-in priorities are:
| Error | Priority | | ------------- | -------: | | required | 100 | | requiredTrue | 100 | | email | 90 | | min | 80 | | max | 80 | | minlength | 70 | | maxlength | 70 | | pattern | 60 | | custom errors | 50 |
Higher priority errors are processed first.
This provides predictable validation message ordering when multiple validators fail at the same time.
Validation Scope
Validation state can identify the scope of a control:
enum ValidationScope {
Control = 'control',
Group = 'group',
Array = 'array'
}The supported scopes represent:
FormControl
FormGroup
FormArrayValidation Source
Validation errors identify their source:
enum ValidationSource {
Angular = 'angular',
Custom = 'custom'
}This allows the validation system to distinguish standard Angular validation errors from custom validation errors.
Global Configuration
The global configuration is provided through:
KITS_VALIDATION_CONFIGConfiguration:
interface ValidationConfig {
readonly visibility: ValidationVisibility;
readonly language: ValidationLanguage;
readonly messages?: Readonly<
Record<string, string>
>;
readonly messageResolver?: (
code: string,
params: ValidationMessageParams | undefined,
language: ValidationLanguage
) => string;
}Example:
{
provide: KITS_VALIDATION_CONFIG,
useValue: {
visibility: 'touched-or-submitted',
language: 'en'
}
}Complete Example
Component
import {
Component,
inject
} from '@angular/core';
import {
FormBuilder,
ReactiveFormsModule,
Validators
} from '@angular/forms';
import {
KitsFormFieldComponent,
ValidationFormDirective
} from 'kits-ngx-validation';
@Component({
selector: 'app-user-form',
standalone: true,
imports: [
ReactiveFormsModule,
KitsFormFieldComponent,
ValidationFormDirective
],
templateUrl: './user-form.component.html'
})
export class UserFormComponent {
private readonly fb = inject(FormBuilder);
readonly form = this.fb.group({
name: [
'',
[
Validators.required,
Validators.minLength(3)
]
],
email: [
'',
[
Validators.required,
Validators.email
]
],
age: [
null,
[
Validators.required,
Validators.min(18)
]
]
});
submit(): void {
if (this.form.invalid) {
return;
}
console.log(
this.form.value
);
}
}Template
<form
kitsValidationForm
[formGroup]="form"
(ngSubmit)="submit()">
<kits-form-field>
<label>
Name
</label>
<input
type="text"
formControlName="name"
/>
</kits-form-field>
<kits-form-field>
<label>
Email
</label>
<input
type="email"
formControlName="email"
/>
</kits-form-field>
<kits-form-field>
<label>
Age
</label>
<input
type="number"
formControlName="age"
/>
</kits-form-field>
<button
type="submit">
Submit
</button>
</form>Public API
The package exports the following main APIs.
Form APIs
ValidationFormDirective
ValidationFormStateService
ValidationControlDirectiveState
ValidationStateServicePresentation
KitsFormFieldComponent
ValidationMessageComponentMessages
ValidationMessageServiceVisibility
ValidationVisibilityServiceModels
ValidationError
ValidationState
ValidationContextEnums
ValidationSource
ValidationScopeConfiguration
KITS_VALIDATION_CONFIG
ValidationConfig
ValidationVisibility
ValidationLanguageContracts
ValidationStateReader
ValidationMessageProvider
ValidationMessageResolverValidators
KitsValidator
KitsUniqueValidatorWhy Use kits-ngx-validation?
Without a shared validation system, large Angular applications commonly end up with:
Feature A
└── custom validation messages
Feature B
└── different validation messages
Feature C
└── different visibility rules
Feature D
└── duplicated validation logickits-ngx-validation provides a shared foundation:
kits-ngx-validation
│
┌──────────────┼──────────────┐
│ │ │
State Messages Visibility
│ │ │
└──────────────┼──────────────┘
│
Angular Reactive Forms
│
┌──────────────┼──────────────┐
│ │ │
Sales Inventory AccountingThis makes validation behavior consistent across an entire application or organization.
Enterprise & ERP Applications
The package is suitable for large applications where validation needs to remain consistent across many features.
Typical use cases include:
- ERP systems
- CRM systems
- Financial applications
- Inventory systems
- Administrative platforms
- Multi-module enterprise applications
- Shared Angular component libraries
- Microfrontend applications
The package has no dependency on a specific UI framework, making it suitable for applications using:
- Angular Material
- PrimeNG
- Tailwind CSS
- Bootstrap
- Custom design systems
- Other Angular UI libraries
Bundle Size & Tree Shaking
The package is designed to be tree-shakable.
Unused exports can be removed by modern Angular build tooling.
The package declares:
{
"sideEffects": false
}The library does not include large UI frameworks or unnecessary runtime dependencies.
Versioning
kits-ngx-validation follows Semantic Versioning:
MAJOR.MINOR.PATCHExample:
1.2.3During the 0.x development phase, APIs may change before the stable 1.0.0 release.
For production applications, it is recommended to control package versions rather than automatically accepting new versions.
Troubleshooting
Validation messages are not displayed
Make sure your form uses:
<form
kitsValidationForm
[formGroup]="form">and that your controls are wrapped with:
<kits-form-field>
...
</kits-form-field>Also verify that the control contains Angular validators:
Validators.requiredor another Angular validator.
Messages appear only after submit
This is expected when using:
visibility: 'submitted'or the default:
visibility: 'touched-or-submitted'For immediate visibility:
visibility: 'always'Custom messages are not used
Make sure the custom error code matches the Angular validation error key.
For example:
{
positiveNumber: true
}requires:
messages: {
positiveNumber: 'Value must be greater than zero'
}Repository
GitHub:
https://github.com/EngYouniss/kits-ngx-validation-package
Issues
Report bugs or request features:
https://github.com/EngYouniss/kits-ngx-validation-package/issues
When opening an issue, include:
- Angular version
kits-ngx-validationversion- TypeScript version
- Browser
- Reproduction steps
- Expected behavior
- Actual behavior
- Error messages if applicable
Contributing
Contributions are welcome.
Before submitting a pull request:
- Install dependencies.
- Build the library.
- Test the library in the demo application.
- Verify the affected functionality.
- Keep changes focused.
- Update documentation when public APIs change.
License
MIT License.
See the repository for the complete license text.
Author
Younis Tallan
GitHub:
https://github.com/EngYouniss
Related
GitHub Repository:
https://github.com/EngYouniss/kits-ngx-validation-package
NPM:
https://www.npmjs.com/package/kits-ngx-validation
kits-ngx-validation — Build consistent, scalable validation for Angular applications.
