A comprehensive Angular application demonstrating advanced reactive form validation with custom validators and dynamic error message handling.
Personal Project by Ibrahim Alnimrawi
π§ Contact: ibrahim.alnimrawi@hotmail.com
- Basic Validators: Required fields, email validation, min/max length
- File Upload Validators: File extension and size validation
- Phone/Mobile Validators: Saudi Arabia phone number formats
- Financial Validators: IBAN validation for Saudi Arabia
- Password Validators: Complex password requirements and confirmation matching
- Text Validators: Alphabetic, Arabic, and numeric-only validation
- ID Validators: National ID validation for Saudi Arabia
- URL Validators: HTTP/HTTPS URL validation
- 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)
- Bootstrap Integration: Responsive design with Bootstrap 5
- Clean Interface: Organized sections with clear labels and placeholders
- Form Status: Real-time form validation status display
- Interactive Elements: Submit/Reset functionality with proper state handling
src/app/
βββ components/
β βββ input-error.component.ts # Error message display component
βββ directives/
β βββ dynamic-validator-message.directive.ts # Dynamic validation directive
β βββ validator-container.directive.ts # Message container directive
βββ pipes/
β βββ message.pipe.ts # Error message transformation pipe
βββ services/
β βββ state-matcher.service.ts # Validation state management
βββ validators/
β βββ _index.ts # Validator exports
β βββ alphabetic-with-special.validator.ts
β βββ arabic-alphabetic.validator.ts
β βββ arabic-alphabetic-with-spaces.validator.ts
β βββ complex-password.validator.ts
β βββ email-address.validator.ts
β βββ file.validator.ts
β βββ iban.validator.ts
β βββ mobile-number.validator.ts
β βββ mobile-or-phone-number.validator.ts
β βββ national-id.validator.ts
β βββ numbers-only.validator.ts
β βββ password-match.validator.ts
β βββ phone-number.validator.ts
β βββ url.validator.ts
βββ value-objects/
βββ validation-error-messages.token.ts # Error message definitions
- Angular 20: Latest Angular framework with standalone components
- Reactive Forms: Advanced form handling with FormBuilder
- TypeScript: Type-safe development
- Bootstrap 5: Modern CSS framework for responsive design
- RxJS: Reactive programming for form state management
Validator | Description | Example |
---|---|---|
required |
Field is mandatory | Any non-empty value |
email |
Valid email format | user@example.com |
minlength |
Minimum character count | 5+ characters |
maxlength |
Maximum character count | β€10 characters |
Validator | Description | Parameters |
---|---|---|
fileValidator |
File extension & size validation | allowedExtensions: string[] , maxFileSizeMB: number |
Validator | Description | Format |
---|---|---|
phoneNumberValidator |
Saudi landline numbers | 01xxxxxxxx |
mobileNumberValidator |
Saudi mobile numbers | 05xxxxxxxx |
mobileOrPhoneNumberValidator |
Either mobile or landline | 01xxxxxxxx or 05xxxxxxxx |
Validator | Description | Format |
---|---|---|
ibanValidator |
Saudi Arabia IBAN validation | SA + 22 digits |
Validator | Description | Requirements |
---|---|---|
complexPasswordValidator |
Strong password validation | 8+ chars, uppercase, lowercase, number, special char |
passwordMatchValidator |
Password confirmation | Must match password field |
Validator | Description | Allowed Characters |
---|---|---|
alphabeticWithSpecialValidator |
Letters, numbers, symbols | a-zA-Z0-9\s\-_.,!@#$%^&*() |
arabicAlphabeticValidator |
Arabic letters only | \u0600-\u06FF |
arabicAlphabeticWithSpacesValidator |
Arabic letters + spaces | \u0600-\u06FF\s |
numbersOnlyValidator |
Numeric input only | 0-9 |
Validator | Description | Format |
---|---|---|
nationalIdValidator |
Saudi National ID | 1 + 9 digits |
Validator | Description | Format |
---|---|---|
urlValidator |
HTTP/HTTPS URLs | https:// or http:// |
- Node.js (v18 or higher)
- npm or yarn
- Angular CLI
# Clone the repository
git clone <repository-url>
cd dynamic-form-validation
# Install dependencies
npm install
# Start development server
npm start
npm run build
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { phoneNumberValidator, emailAddressValidator } from './validators/_index';
export class MyComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
email: ['', [Validators.required, emailAddressValidator]],
phone: ['', phoneNumberValidator],
password: ['', complexPasswordValidator],
confirmPassword: ['', Validators.required]
}, { validators: passwordMatchValidator });
}
}
<form [formGroup]="form" MessageContainer>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input
type="email"
id="email"
class="form-control"
formControlName="email"
placeholder="Enter your email">
</div>
<button type="submit" [disabled]="form.invalid">
Submit
</button>
</form>
- Create validator file in
src/app/validators/
- Export validator from
_index.ts
- Add error message to
validation-error-messages.token.ts
- Use in form definition
// In validation-error-messages.token.ts
export const ERROR_MESSAGES = {
customValidator: ({ minValue }) => `Value must be at least ${minValue}`,
// ... other messages
};
/* Custom error styling */
.text-danger {
color: #dc3545;
font-size: 0.875rem;
margin-top: 0.25rem;
}
.form-control.text-danger {
border-color: #dc3545;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
- 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
// Valid test data
const validData = {
requiredField: 'Test Value',
emailField: 'test@example.com',
phoneNumber: '0123456789',
mobileNumber: '0512345678',
ibanField: 'SA0380000000608010167519',
password: 'MySecure123!',
confirmPassword: 'MySecure123!',
nationalId: '1234567890',
websiteUrl: 'https://example.com'
};
- Selector:
[formControl]:not([withoutValidation])
- Purpose: Automatically handles validation display for form controls
- Features: Error borders, dynamic error messages, state management
- Selector:
[MessageContainer]
- Purpose: Provides container for error message components
- Usage: Applied to form element
- Purpose: Determines when to show validation errors
- Methods:
isErrorVisible(control, form)
- Behavior: Shows errors when field is dirty/touched and form is submitted
This is a personal project created for demonstration and learning purposes.
- Angular Team for the excellent framework
- Bootstrap Team for the CSS framework
- Open source community for inspiration and resources
Project Author: Ibrahim Alnimrawi
π§ Email: ibrahim.alnimrawi@hotmail.com
For questions, feedback, or collaboration opportunities, feel free to reach out!
Built with β€οΈ by Ibrahim Alnimrawi using Angular 20