Hone logo
Hone
Problems

Implementing Reactive Radio Button Binding in Vue.js with TypeScript

This challenge focuses on creating a reusable component in Vue.js that provides reactive binding for radio buttons. Radio buttons are commonly used for selecting a single option from a set, and this component will ensure that the selected value is consistently updated in the parent component and vice versa. This is a fundamental pattern for form handling and user input in Vue applications.

Problem Description

You are tasked with building a RadioGroup component in Vue.js using TypeScript. This component will accept an array of radio button options, each with a value and a label. The component should maintain an internal modelValue representing the currently selected radio button's value. Crucially, the component must emit an update:modelValue event whenever the selected radio button changes, allowing the parent component to react to the selection. The component should also react to changes in the modelValue prop, updating the selected radio button accordingly.

Key Requirements:

  • Props:
    • modelValue: (string | number | null) - The currently selected value.
    • options: (Array<{ value: string | number; label: string }>) - An array of radio button options.
  • Events:
    • update:modelValue: (string | number) - Emitted when the selected radio button changes.
  • Reactivity: The component must be reactive to both prop changes (modelValue) and user interactions (radio button clicks).
  • Accessibility: Ensure the radio buttons are accessible (e.g., proper labels, ARIA attributes).
  • Type Safety: Leverage TypeScript to ensure type safety throughout the component.

Expected Behavior:

  1. When the component is initialized with a modelValue, the corresponding radio button should be pre-selected.
  2. When a radio button is clicked, the update:modelValue event should be emitted with the selected value.
  3. When the modelValue prop changes, the corresponding radio button should be selected.
  4. If modelValue is null or undefined, no radio button should be selected.
  5. The component should render all provided options as radio buttons with their respective labels.

Edge Cases to Consider:

  • Empty options array.
  • modelValue not present in any of the options values.
  • options array containing duplicate values (should be handled gracefully, potentially by only selecting the first matching option).
  • modelValue being a type that doesn't match the value type of the options (e.g., string modelValue and number options.value). Consider type coercion or throwing an error.

Examples

Example 1:

Input:
options: [{ value: 'A', label: 'Option A' }, { value: 'B', label: 'Option B' }]
modelValue: 'B'
Output:
Radio button with value 'B' and label 'Option B' is selected. Radio button with value 'A' and label 'Option A' is unselected.
Explanation: The component initializes with 'B' as the selected value, so the corresponding radio button is pre-selected.

Example 2:

Input:
options: [{ value: 1, label: 'One' }, { value: 2, label: 'Two' }, { value: 3, label: 'Three' }]
modelValue: null
Output:
No radio button is selected.
Explanation: The component initializes with a null modelValue, so no radio button is selected.

Example 3:

Input:
options: [{ value: 'X', label: 'X' }, { value: 'Y', label: 'Y' }]
modelValue: 'Z'
Output:
No radio button is selected.
Explanation: The modelValue 'Z' does not match any of the option values, so no radio button is selected.

Constraints

  • The component must be written in Vue 3 with TypeScript.
  • The component should be reusable and easily integrated into other Vue components.
  • The component should be reasonably performant, even with a large number of options (e.g., avoid unnecessary re-renders).
  • The options array should not be mutated directly within the component. Changes to the parent's options array should be reflected in the component.

Notes

  • Consider using v-model for two-way binding with the parent component.
  • Think about how to handle different data types for modelValue and options.value. Type coercion might be appropriate, or you could throw an error if the types don't match.
  • Pay close attention to the update:modelValue event and how it interacts with v-model.
  • Focus on creating a clean, well-documented, and testable component.
  • Accessibility is important - ensure your radio buttons are usable by everyone.
Loading editor...
typescript