Angular Custom Form Validators
This challenge focuses on implementing custom validation logic within Angular forms. You will create reusable validator functions that can be applied to form controls, enhancing the form's data integrity and user experience. This is a fundamental skill for building robust Angular applications.
Problem Description
Your task is to create a set of custom asynchronous and synchronous validators for an Angular FormControl. You will then integrate these validators into a simple form component and display appropriate error messages based on the validation results.
Key Requirements:
- Create a Synchronous Validator: Implement a validator that checks if a given string input contains only alphanumeric characters (a-z, A-Z, 0-9).
- Create an Asynchronous Validator: Implement a validator that checks if a username is unique by simulating a delay and then returning a validation result. This will mimic a server-side check.
- Integrate Validators into a Form: Create a simple Angular component with a
FormGroupand aFormControlfor a username. Apply both the synchronous and asynchronous validators to thisFormControl. - Display Error Messages: Based on the validation status of the
FormControl, display user-friendly error messages within the component's template. - Handle Validation States: Ensure that error messages are only displayed when the control is touched (or dirty) and has validation errors.
Expected Behavior:
- When the user types into the username input:
- If the input contains non-alphanumeric characters, an "Invalid characters" error should appear.
- If the input is valid according to the synchronous validator, but it's a "taken" username (as determined by your asynchronous validator), a "Username already taken" error should appear after a short delay.
- If the input is valid and not taken, no error should be displayed.
- Error messages should only appear after the user has interacted with the input (e.g., blurred from it or typed in it).
Edge Cases:
- Empty input: Should be considered valid by the alphanumeric validator.
- Case sensitivity: The alphanumeric validator should be case-insensitive.
- Asynchronous validation feedback: Provide some visual indication (e.g., disabling the submit button or showing a loading spinner, though the spinner is optional for this challenge) while the asynchronous validator is running.
Examples
Example 1: Synchronous Validator - Invalid Characters
Input:
Username FormControl value: "john_doe123"
Output:
An error message indicating "Invalid characters" should be displayed.
Explanation:
The underscore character is not alphanumeric, so the synchronous validator fails.
Example 2: Synchronous Validator - Valid Characters
Input:
Username FormControl value: "JohnDoe123"
Output:
No error message related to invalid characters. The asynchronous validator will proceed.
Explanation:
All characters are alphanumeric.
Example 3: Asynchronous Validator - Username Taken
Input:
Username FormControl value: "admin" (assuming "admin" is a pre-defined taken username)
Output:
After a simulated delay, an error message indicating "Username already taken" should be displayed.
Explanation:
The synchronous validator passes, but the asynchronous validator (simulating a server check) finds that "admin" is already in use.
Example 4: Asynchronous Validator - Username Available
Input:
Username FormControl value: "uniqueUser456" (assuming "uniqueUser456" is not a pre-defined taken username)
Output:
No error message related to username availability after the simulated delay.
Explanation:
The synchronous validator passes, and the asynchronous validator confirms the username is available.
Constraints
- The asynchronous validator must simulate a network delay of at least 1 second using
setTimeout. - The list of "taken" usernames for the asynchronous validator can be a hardcoded array of strings within your validator logic.
- The solution should be implemented using Angular's Reactive Forms API.
- No external validation libraries are allowed.
Notes
- You'll need to create a custom validator function that returns
nullif the validation passes and an object with an error key (e.g.,{ invalidChars: true }or{ usernameTaken: true }) if it fails. - For asynchronous validators, the return type will be
Observable<ValidationErrors | null>. - Remember to handle the
touchedordirtystate of the form control when deciding whether to display error messages in the template. - Consider how to display feedback during the asynchronous validation process, even if it's just a simple text indicator or disabling the submit button.