Hone logo
Hone
Problems

Async Form Validation in Vue.js with TypeScript

This challenge focuses on implementing robust asynchronous validation for a form in a Vue.js application using TypeScript. Asynchronous validation is crucial for scenarios like checking for unique usernames or emails against a backend API, providing immediate feedback to the user without blocking their interaction.

Problem Description

You are tasked with building a Vue component that includes a form with an input field. This input field requires validation, specifically an asynchronous check to see if the entered value (e.g., a username) is already taken.

Key Requirements:

  1. Vue Component: Create a single-file Vue component (.vue) using TypeScript.
  2. Input Field: Include a standard HTML input element for user entry.
  3. Async Validation Logic: Implement a function that simulates an asynchronous check (e.g., using setTimeout to mimic an API call). This function should return true if the value is available and false if it's already taken.
  4. Real-time Feedback:
    • Display an error message below the input field when the asynchronous validation fails.
    • Indicate when the validation is in progress (e.g., disable the submit button or show a loading spinner).
    • Clear the error message when the validation succeeds or the input is cleared.
  5. State Management: Use Vue's reactivity system (e.g., ref, reactive) to manage the input value, validation status (valid/invalid), and loading state.
  6. TypeScript: Ensure all code is written in TypeScript, including type definitions for component props, state, and validation functions.

Expected Behavior:

  • As the user types, the asynchronous validation should trigger after a short delay (e.g., 500ms) to avoid excessive API calls.
  • If the async validation returns false, an error message like "This username is already taken." should appear.
  • While the validation is in progress, a visual indicator should be present (e.g., a "Validating..." message or a disabled submit button).
  • If the async validation returns true, no error message should be displayed.
  • Clearing the input field should reset the validation state and remove any error messages.

Edge Cases:

  • Debouncing: Implement debouncing for the validation trigger to prevent overwhelming the (simulated) API.
  • Input Clearing: Ensure validation state is correctly reset when the user clears the input.
  • Rapid Typing: Handle scenarios where the user types very quickly, ensuring only the latest validation request is considered.

Examples

Example 1: Valid Input

Input State:
- Input Value: "newuser"
- Is Validating: true (after typing)

Simulated API Response (after 500ms): true

Output:
- Input Field: "newuser"
- Error Message: (None)
- Validation Status: Valid
- Loading Indicator: (Gone)

Example 2: Invalid Input

Input State:
- Input Value: "existinguser"
- Is Validating: true (after typing)

Simulated API Response (after 500ms): false

Output:
- Input Field: "existinguser"
- Error Message: "This username is already taken."
- Validation Status: Invalid
- Loading Indicator: (Gone)

Example 3: Debouncing and Clearing

Scenario:
1. User types "a". Validation starts.
2. User quickly types "b". Previous validation for "a" is cancelled/ignored. Validation for "b" starts.
3. User clears the input.

Input State:
- Initial Input Value: ""
- After step 1: "a"
- After step 2: "b"
- After step 3: ""

Simulated API Responses:
- For "a": true (if it had completed)
- For "b": false

Output:
- Input Field: ""
- Error Message: (None)
- Validation Status: Valid (or initial state)
- Loading Indicator: (Gone)

Constraints

  • The simulated asynchronous validation function must return a Promise<boolean>.
  • The delay for the simulated API call should be a configurable constant within the component (e.g., const VALIDATION_DELAY = 500;).
  • The debouncing delay should be a separate configurable constant (e.g., const DEBOUNCE_DELAY = 300;).
  • The solution should be a single .vue file.

Notes

  • Consider using a library like lodash for debouncing if you prefer, but implementing it manually is also a good exercise.
  • Think about how to manage the state of the validation process (e.g., isInvalid, isLoading).
  • The error message should be displayed only when isInvalid is true and isLoading is false.
  • The loading indicator should be visible only when isLoading is true.
Loading editor...
typescript