@ibrahimalnimrawi/angular-dynamic-validation
v2.0.1
Published
A comprehensive Angular library for dynamic form validation with extendable error messages and real-time validation feedback
Maintainers
Readme
Angular Dynamic Validation Library v2.0.0
A highly dynamic and extendable Angular library for form validation with real-time feedback, customizable styling, and advanced validation rules management.
🚀 Features
✨ Dynamic Validation System
- Real-time Validation: Instant feedback as users type
- Custom Error Messages: Localized error messages with dynamic parameters
- Visual Feedback: Error borders and styling for invalid fields
- State Management: Smart error display based on field state (dirty, touched, submitted)
- Success States: Optional success state styling for valid fields
- Animation Support: Smooth transitions between validation states
🎨 Highly Customizable Styling
- Multiple Themes: Default, Material Design, Bootstrap, and Custom themes
- Dynamic CSS Classes: Automatic class management without space character issues
- Custom Styles: Inline styles and CSS class customization
- Responsive Design: Mobile-first approach with flexible layouts
- Accessibility: Focus management and screen reader support
🔧 Extensible Architecture
- Validator Factory: Create custom validators with
ValidatorFactoryService - Advanced Validation Service: Dynamic rule management and registration
- Configuration Service: Global validation configuration management
- Custom Validation Rules: Register and manage custom validation logic
- Plugin System: Extend functionality with custom providers
📦 Pre-built Validators
- Email validation
- Phone number validation (Saudi format)
- Mobile number validation
- IBAN validation
- National ID validation
- URL validation
- Password strength validation
- File validation
- Cross-field validation (password matching)
📦 Installation
npm install @ibrahimalnimrawi/angular-dynamic-validation🚀 Quick Start
1. Import the Module
import { DynamicValidationModule } from '@ibrahimalnimrawi/angular-dynamic-validation';
@NgModule({
imports: [DynamicValidationModule]
})
export class AppModule { }2. Basic Usage
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { CommonValidators } from '@ibrahimalnimrawi/angular-dynamic-validation';
@Component({
selector: 'app-my-form',
template: `
<form [formGroup]="form" MessageContainer>
<input
type="email"
class="dynamic-validation-input"
formControlName="email"
placeholder="Enter email">
<input
type="tel"
class="dynamic-validation-input"
formControlName="phone"
placeholder="Enter phone">
</form>
`
})
export class MyFormComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
email: ['', [Validators.required, CommonValidators.email]],
phone: ['', CommonValidators.phoneNumber]
});
}
}🎨 Advanced Styling & Theming
Theme Configuration
import { ValidationConfigService } from '@ibrahimalnimrawi/angular-dynamic-validation';
@Component({...})
export class AppComponent {
constructor(private configService: ValidationConfigService) {
// Set Material Design theme
this.configService.setTheme('material');
// Or Bootstrap theme
this.configService.setTheme('bootstrap');
// Or custom theme
this.configService.setTheme('custom');
}
}Custom Styling Configuration
import { ValidationStyleConfig } from '@ibrahimalnimrawi/angular-dynamic-validation';
// In your component
const customConfig: ValidationStyleConfig = {
baseClass: 'my-input',
errorClass: 'my-error',
successClass: 'my-success',
customStyles: {
'border-radius': '8px',
'padding': '12px'
},
errorStyles: {
'border-color': '#ff4444',
'box-shadow': '0 0 0 3px rgba(255, 68, 68, 0.2)'
},
successStyles: {
'border-color': '#44ff44',
'box-shadow': '0 0 0 3px rgba(68, 255, 68, 0.2)'
}
};Template Usage with Custom Configuration
<form [formGroup]="form" MessageContainer>
<input
type="email"
formControlName="email"
[validationConfig]="customConfig"
[showSuccessState]="true"
[validationTriggers]="['blur', 'change']">
</form>🔧 Advanced Validation System
Using Advanced Validation Service
import { AdvancedValidationService, COMMON_VALIDATION_RULES } from '@ibrahimalnimrawi/angular-dynamic-validation';
@Component({...})
export class MyComponent {
constructor(private validationService: AdvancedValidationService) {
// Register common rules
this.validationService.registerRules(COMMON_VALIDATION_RULES);
// Register custom rule
this.validationService.registerRule({
name: 'customRule',
validator: (control) => {
return control.value?.includes('special') ? null : { customRule: true };
},
message: 'Value must contain "special"',
priority: 1
});
}
createForm() {
// Create validator from rule names
const customValidator = this.validationService.createValidator(['required', 'email', 'customRule']);
this.form = this.fb.group({
email: ['', customValidator]
});
}
}Dynamic Validator Creation
import { ValidatorFactoryService } from '@ibrahimalnimrawi/angular-dynamic-validation';
// Pattern-based validator
const customPattern = ValidatorFactoryService.pattern('customPattern', /^[A-Z]{3}\d{3}$/);
// Length validator
const customLength = ValidatorFactoryService.length('customLength', 5, 20);
// Range validator for numbers
const customRange = ValidatorFactoryService.range('customRange', 1, 100);
// Custom logic validator
const customLogic = ValidatorFactoryService.custom('customLogic', (value) => {
return value.includes('special') ? true : 'Value must contain "special"';
});
// File validator
const fileValidator = ValidatorFactoryService.file('fileError', ['jpg', 'png'], 5);
// Password strength validator
const passwordStrength = ValidatorFactoryService.passwordStrength('passwordStrength', {
minLength: 8,
requireUppercase: true,
requireLowercase: true,
requireNumbers: true,
requireSpecialChars: true
});
// Cross-field validator
const passwordMatch = ValidatorFactoryService.crossField(
'passwordMismatch',
'password',
(password, confirmPassword) => password === confirmPassword
);🎯 Global Configuration
Setting Global Validation Configuration
import { ValidationConfigService } from '@ibrahimalnimrawi/angular-dynamic-validation';
@Component({...})
export class AppComponent {
constructor(private configService: ValidationConfigService) {
// Enable success states globally
this.configService.setSuccessState(true);
// Set validation triggers
this.configService.setValidationTriggers(['blur', 'change']);
// Set animation duration
this.configService.setAnimationDuration(500);
// Update global configuration
this.configService.updateConfig({
showSuccessState: true,
validationTriggers: ['blur', 'change', 'submit'],
animationDuration: 300
});
}
}🎨 CSS Classes Reference
Container Classes
dynamic-validation-container- Main container wrapperdynamic-validation-form- Form wrapper with card stylingdynamic-validation-section- Section groupingdynamic-validation-section-title- Section headings
Layout Classes
dynamic-validation-row- Flex row containerdynamic-validation-col- Flexible columndynamic-validation-col-half- 50% width columndynamic-validation-col-third- 33.33% width columndynamic-validation-col-quarter- 25% width column
Form Classes
dynamic-validation-group- Form field groupdynamic-validation-label- Form labelsdynamic-validation-label.required- Required field labelsdynamic-validation-input- Form inputsdynamic-validation-input.error- Error state inputsdynamic-validation-input.success- Success state inputs
Action Classes
dynamic-validation-actions- Button containerdynamic-validation-btn- Base button classdynamic-validation-btn-primary- Primary buttondynamic-validation-btn-secondary- Secondary buttondynamic-validation-btn-info- Info button
Status Classes
dynamic-validation-status- Status message containerdynamic-validation-status.success- Success statusdynamic-validation-status.error- Error statusdynamic-validation-status.info- Info status
Error Classes
dynamic-validation-error- Error message text
🔧 Extending Error Messages
Using ValidationMessageService
import { ValidationMessageService } from '@ibrahimalnimrawi/angular-dynamic-validation';
@Component({...})
export class MyComponent {
constructor(private messageService: ValidationMessageService) {}
ngOnInit() {
// Add custom messages
this.messageService.addMessages({
customError: () => 'This is a custom error message!',
minLength: ({ requiredLength, actualLength }) =>
`Minimum length is ${requiredLength}, but you entered ${actualLength} characters`
});
// Add a single message
this.messageService.addMessage('phoneNumber', () => 'Custom phone validation message!');
}
}Custom Message Provider
import { Injectable } from '@angular/core';
import { MessageProvider, ValidationErrorMessage } from '@ibrahimalnimrawi/angular-dynamic-validation';
@Injectable()
export class CustomMessageProvider implements MessageProvider {
private messages: { [key: string]: ValidationErrorMessage } = {};
getMessage(key: string, args?: any): string {
const messageFn = this.messages[key];
return messageFn ? messageFn(args) : `Unknown error: ${key}`;
}
// ... implement other methods
}
// Provide it in your module
@NgModule({
providers: [
{ provide: MessageProvider, useClass: CustomMessageProvider }
]
})
export class AppModule { }🧪 Testing
Manual Testing Scenarios
- Required Fields: Leave empty and verify error messages
- Email Validation: Test invalid email formats
- Phone Numbers: Test various phone number formats
- File Upload: Test file size and extension restrictions
- Password Strength: Test password complexity requirements
- Password Matching: Test password confirmation validation
Test Data Examples
// Valid test data
const validData = {
requiredField: 'Test Value',
emailField: '[email protected]',
phoneNumber: '0123456789',
mobileNumber: '0512345678',
ibanField: 'SA0380000000608010167519',
password: 'MySecure123!',
confirmPassword: 'MySecure123!',
nationalId: '1234567890',
websiteUrl: 'https://example.com'
};📚 API Reference
DynamicValidatorMessage Directive
- Selector:
[formControlName]:not([withoutValidation]) - Purpose: Automatically handles validation display for form controls
- Features: Error borders, dynamic error messages, state management
MessageContainer Directive
- Selector:
[MessageContainer] - Purpose: Provides container for error message components
- Usage: Applied to form element
AdvancedValidationService
- Purpose: Dynamic validation rule management
- Methods:
registerRule(),createValidator(),getErrorMessage() - Features: Custom rule registration, dynamic validator creation
ValidationConfigService
- Purpose: Global validation configuration management
- Methods:
setTheme(),updateConfig(),setSuccessState() - Features: Theme management, global configuration
🚀 Migration Guide
From v1.x to v2.0
The new version is fully backward compatible. However, to take advantage of new features:
- Update imports:
// Old
import { DynamicValidationModule } from '@ibrahimalnimrawi/angular-dynamic-validation';
// New (same, but with additional services available)
import {
DynamicValidationModule,
AdvancedValidationService,
ValidationConfigService
} from '@ibrahimalnimrawi/angular-dynamic-validation';- Use new styling system:
// Old way
@Input() errorBorderClass: string = 'dynamic-validation-input error';
// New way (automatic, no space issues)
const config: ValidationStyleConfig = {
baseClass: 'dynamic-validation-input',
errorClass: 'error'
};🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Angular Team for the excellent framework
- Open source community for inspiration and resources
📞 Contact & Support
Project Author: Ibrahim Alnimrawi
📧 Email: [email protected]
For questions, feedback, or collaboration opportunities, feel free to reach out!
Built with ❤️ by Ibrahim Alnimrawi using Angular 20
