Hone logo
Hone
Problems

Building a Controlled Input Component in Vue with TypeScript

This challenge focuses on creating a reusable, controlled input component in Vue.js using TypeScript. Controlled components are crucial for managing form data effectively and ensuring predictable behavior, especially when dealing with complex validation or external data sources.

Problem Description

You are tasked with building a ControlledInput component that allows users to input text and updates a parent component's data in real-time. The component should accept a modelValue prop (representing the initial value and the data source) and emit an update:modelValue event whenever the input changes. The component should also accept a type prop to specify the input type (e.g., "text", "number", "email"). Proper TypeScript typing is essential for code clarity and maintainability.

Key Requirements:

  • modelValue Prop: The component must accept a modelValue prop of type string. This prop represents the current value of the input and the data source that the component will update.
  • update:modelValue Event: The component must emit an update:modelValue event whenever the input value changes. The event payload should be the new input value.
  • type Prop: The component must accept a type prop of type string to specify the input type. Default to "text" if no type is provided.
  • Two-Way Binding: The component should effectively implement two-way data binding, where changes in the input field update the modelValue prop in the parent component.
  • TypeScript: The component must be written in TypeScript with appropriate type annotations for props, events, and internal variables.

Expected Behavior:

  1. When the component is initialized, the input field should display the value of the modelValue prop.
  2. As the user types in the input field, the update:modelValue event should be emitted with the current input value.
  3. The parent component should listen for the update:modelValue event and update its data accordingly.
  4. The input type should be set according to the type prop.

Edge Cases to Consider:

  • Initial modelValue being an empty string.
  • type prop being an invalid value (handle gracefully, defaulting to "text").
  • The parent component not providing a modelValue. (Consider providing a default value or throwing a warning).

Examples

Example 1:

Input:
Parent Component: data = { message: "Hello" }
ControlledInput component with modelValue="message"
Output:
Input field displays "Hello".  When the user types "World", the parent component's data.message is updated to "World".
Explanation: The input field is initially bound to the parent's data. User input updates the parent's data.

Example 2:

Input:
Parent Component: data = { username: "" }
ControlledInput component with modelValue="username" and type="email"
Output:
Input field displays an empty string. The input field is of type "email". When the user types "test@example.com", the parent component's data.username is updated to "test@example.com".
Explanation: The input field is initially bound to the parent's data. The input type is set to email. User input updates the parent's data.

Example 3: (Edge Case)

Input:
Parent Component: data = { name: undefined }
ControlledInput component with modelValue="name"
Output:
Input field displays an empty string.  The parent component's data.name is updated with the input value.
Explanation: Handles undefined initial value gracefully by defaulting to an empty string.

Constraints

  • The component must be a single-file Vue component (.vue file).
  • The component must be written in TypeScript.
  • The component should be reusable and easily integrated into other Vue components.
  • The component should not have any external dependencies beyond Vue and TypeScript.
  • The component should be reasonably performant (avoid unnecessary re-renders).

Notes

  • Consider using v-model in the parent component to simplify the data binding process.
  • Think about how to handle potential errors or invalid input values. While validation isn't explicitly required, consider how the component could be extended to support it.
  • Focus on creating a clean, well-documented, and maintainable component.
  • Remember that modelValue is the prop and update:modelValue is the event. The v-model directive in the parent component automatically handles these.
Loading editor...
typescript