Hone logo
Hone
Problems

Vue Select Binding with TypeScript

This challenge focuses on implementing a two-way data binding for a select element in a Vue.js application using TypeScript. Two-way binding allows changes in the select element to update a data property in the Vue component, and vice versa, ensuring the UI and data remain synchronized. This is a fundamental concept in Vue and crucial for building interactive user interfaces.

Problem Description

You are tasked with creating a reusable Vue component that provides two-way data binding for a select element. The component should accept the following props:

  • modelValue: (string | number | null) - The currently selected value. This is the value that will be bound to the component's data. It can be a string, number, or null.
  • options: (Array<{label: string, value: string | number}>) - An array of objects, where each object represents an option in the select element. Each option object must have a label (string) and a value (string or number) property.
  • labelKey: (string) - The key to use for the label in the options. Defaults to 'label'.
  • valueKey: (string) - The key to use for the value in the options. Defaults to 'value'.

The component should emit an update:modelValue event whenever the selected option changes. This event should carry the new value of the selected option.

Key Requirements:

  • Implement two-way data binding between the modelValue prop and the select element's selected value.
  • Render the options array as <option> elements within the select element.
  • Ensure that the currently selected option's value matches the modelValue prop.
  • Handle the case where modelValue is null or undefined (no option is selected).
  • Use TypeScript for type safety.

Expected Behavior:

  1. When the component is initialized, the select element should display options based on the options prop.
  2. The initially selected option should be the one whose value matches the modelValue prop. If modelValue is null/undefined, no option should be selected.
  3. When the user selects a different option from the select element, the update:modelValue event should be emitted with the value of the selected option.
  4. When the modelValue prop changes externally, the select element should update to reflect the new selected value.

Edge Cases to Consider:

  • Empty options array: The select element should be empty.
  • modelValue not present in any option's value: No option should be selected.
  • options array contains duplicate values: The behavior is undefined, but the component should not crash. Ideally, only the first matching option should be selected.

Examples

Example 1:

Input:
options = [{label: 'Option 1', value: 1}, {label: 'Option 2', value: 2}]
modelValue = 1

Output:

<select>
  <option value="1">Option 1</option>
  <option value="2">Option 2</option>
</select>

Explanation: The select element displays two options, and "Option 1" is pre-selected because its value (1) matches the modelValue.

Example 2:

Input:
options = [{label: 'Red', value: 'red'}, {label: 'Green', value: 'green'}]
modelValue = 'blue'

Output:

<select>
  <option value="red">Red</option>
  <option value="green">Green</option>
</select>

Explanation: The select element displays two options, and no option is selected because the modelValue ('blue') does not match any of the option values.

Example 3:

Input:
options = []
modelValue = 5

Output:

<select>
</select>

Explanation: The select element is empty because the options array is empty.

Constraints

  • The component should be written in Vue 3 with the Composition API.
  • The component should be written in TypeScript.
  • The component should be reusable and accept the specified props.
  • The component should emit the update:modelValue event correctly.
  • The component should handle edge cases gracefully.
  • The component should be reasonably performant (rendering a large number of options should not cause significant performance issues). Assume a maximum of 100 options.

Notes

  • Consider using the v-model directive to simplify the two-way data binding.
  • Pay close attention to the type definitions for the props and emitted event.
  • Think about how to handle the case where the modelValue is not found in the options array.
  • This is a fundamental building block for many Vue applications, so focus on creating a clean, well-documented, and reusable component.
Loading editor...
typescript