Custom Email Validator Directive in Angular
This challenge asks you to create a reusable Angular directive that validates whether a given input field contains a valid email address. Building custom directives for validation is a powerful way to encapsulate validation logic, promote code reusability, and maintain a clean component structure in Angular applications. This directive will enhance form validation and improve the user experience.
Problem Description
You need to create an Angular directive named emailValidator that can be applied to any input element. When the directive is applied, it should:
- Listen for changes in the input field's value.
- Validate the input value against a regular expression for email format.
- Add or remove a CSS class (
invalid-email) to the input element based on the validation result. The class should be added when the email is invalid and removed when it's valid. - Emit a custom event called
emailValidwhen the email is valid andemailInvalidwhen the email is invalid. This allows parent components to react to validation changes.
Key Requirements:
- The directive must be reusable and applicable to any input element.
- The validation logic should be encapsulated within the directive.
- The directive should provide visual feedback to the user (through the CSS class).
- The directive should allow parent components to be notified of validation status.
Expected Behavior:
- When the directive is initialized, it should not add or remove the
invalid-emailclass. - As the user types in the input field, the directive should continuously validate the input.
- If the input is a valid email address, the
invalid-emailclass should be removed, and theemailValidevent should be emitted. - If the input is an invalid email address, the
invalid-emailclass should be added, and theemailInvalidevent should be emitted. - If the input field is cleared, the
invalid-emailclass should be removed, and theemailValidevent should be emitted.
Edge Cases to Consider:
- Empty input field: Should be considered valid (no error).
- Whitespace-only input: Should be considered invalid.
- Very long email addresses: The regular expression should handle them gracefully.
- Special characters in email addresses: The regular expression should allow for valid special characters.
Examples
Example 1:
Input: <input type="email" emailValidator (emailValid)="onEmailValid()" (emailInvalid)="onEmailInvalid()">
Initial Value: ""
Output: No CSS class applied. `emailValid` event emitted.
Explanation: An empty input is considered valid.
Example 2:
Input: <input type="email" emailValidator (emailValid)="onEmailValid()" (emailInvalid)="onEmailInvalid()">
Value: "test@example.com"
Output: No CSS class applied. `emailValid` event emitted.
Explanation: A valid email address.
Example 3:
Input: <input type="email" emailValidator (emailValid)="onEmailValid()" (emailInvalid)="onEmailInvalid()">
Value: "invalid-email"
Output: CSS class `invalid-email` applied. `emailInvalid` event emitted.
Explanation: An invalid email address.
Example 4: (Edge Case)
Input: <input type="email" emailValidator (emailValid)="onEmailValid()" (emailInvalid)="onEmailInvalid()">
Value: " " (Whitespace only)
Output: CSS class `invalid-email` applied. `emailInvalid` event emitted.
Explanation: Whitespace only is considered invalid.
Constraints
- The regular expression for email validation should be reasonably robust but doesn't need to be perfectly RFC compliant. A common and practical regex is acceptable.
- The directive should be implemented using Angular's directive lifecycle hooks.
- The directive should not modify the input element's value directly.
- The directive should be compatible with Angular version 14 or higher.
- Performance: The validation should be efficient enough to not cause noticeable lag while the user is typing.
Notes
- Consider using
@Input()to allow customization of the CSS class name if needed (though this is not required for the core functionality). - The regular expression is a key part of this challenge. Research and choose a suitable one.
- Think about how to handle the initial state of the input field when the directive is applied.
- Use Angular's
EventEmitterto emit the custom events. - Remember to declare the directive in a module.