Hone logo
Hone
Problems

Vue Change Detection: Tracking User Modifications

This challenge focuses on implementing a robust change detection mechanism within a Vue.js application. You'll build a component that monitors user input in a form and accurately indicates whether any changes have been made from the original data. This is crucial for features like "Save Changes" buttons, preventing data loss on navigation, and providing clear user feedback.

Problem Description

Your task is to create a Vue.js component that manages a form and tracks changes made by the user. The component should:

  • Display a form: Present a set of input fields (e.g., text inputs, checkboxes, select dropdowns) pre-populated with initial data.
  • Detect changes: Compare the current state of the form inputs with their initial values.
  • Indicate changes: Visually signal to the user when any changes have been made. This could be through a message, a styling change, or a "dirty" flag.
  • Reset changes: Provide a mechanism to revert the form to its original state.
  • Handle nested data: The initial data might be a nested object. Your change detection should account for modifications within these nested structures.

Key Requirements:

  • Use Vue 3 Composition API and TypeScript.
  • The component should accept an initialData prop, which is an object representing the starting state of the form.
  • Implement a reactive way to track the form's current state.
  • Provide a clear visual indicator for the "dirty" state (i.e., whether changes have been made).
  • Implement a resetForm function to revert all changes.
  • Consider how to handle different input types effectively.

Expected Behavior:

  1. When the component loads, the form should display the initialData.
  2. The "dirty" indicator should be off initially.
  3. As the user types or modifies any form field, the "dirty" indicator should turn on.
  4. If the user interacts with the form and then resets it, the form should revert to initialData, and the "dirty" indicator should turn off.
  5. If the initialData prop is updated externally, the form should reflect the new initialData and reset its dirty state.

Edge Cases to Consider:

  • Empty initial data: What happens if initialData is an empty object?
  • Different data types: Ensure correct comparison for strings, numbers, booleans, and arrays.
  • Programmatic changes: While not strictly required for this challenge, think about how programmatic updates to form fields might affect change detection. (Focus on user-driven changes for this problem).
  • Deeply nested objects: Ensure changes deep within nested objects are detected.

Examples

Example 1: Basic Text Input

Input (initialData prop):
{
  name: "John Doe",
  email: "john.doe@example.com"
}

User Interaction:
- User changes 'name' to "Jane Doe"

Expected Output (Visual Indication):
"Changes detected!" (or similar)
"dirty" state is true.

User Interaction:
- User clicks a "Reset" button.

Expected Output (Visual Indication):
No indication of changes.
"dirty" state is false.
Form reverts to:
{
  name: "John Doe",
  email: "john.doe@example.com"
}

Example 2: Nested Object and Checkbox

Input (initialData prop):
{
  userProfile: {
    firstName: "Alice",
    lastName: "Smith"
  },
  settings: {
    notificationsEnabled: true
  }
}

User Interaction:
- User changes 'firstName' to "Alicia"
- User unchecks 'notificationsEnabled'

Expected Output (Visual Indication):
"Changes detected!"
"dirty" state is true.

User Interaction:
- User clicks "Reset".

Expected Output (Visual Indication):
No indication of changes.
"dirty" state is false.
Form reverts to:
{
  userProfile: {
    firstName: "Alice",
    lastName: "Smith"
  },
  settings: {
    notificationsEnabled: true
  }
}

Example 3: Empty Initial Data and New Input

Input (initialData prop):
{}

User Interaction:
- User types "New Value" into a text field.

Expected Output (Visual Indication):
"Changes detected!"
"dirty" state is true.

Constraints

  • The initialData prop will be a plain JavaScript object.
  • The depth of nested objects will not exceed 5 levels.
  • The total number of form fields will be manageable (e.g., < 50).
  • The component should be performant enough for real-time feedback without noticeable lag.
  • All logic must be implemented using TypeScript within the Vue 3 Composition API.

Notes

  • Consider using watch or watchEffect for reactive tracking.
  • Deep comparison of objects might be necessary to accurately detect changes in nested structures. Libraries like Lodash offer utility functions for deep equality, or you can implement your own.
  • Think about how to store and compare the initial state with the current state effectively. A common approach is to create a deep copy of the initialData when the component mounts and use it as the reference point.
  • The visual indicator can be as simple as a <div> displaying text, or a boolean isDirty flag that can be used to conditionally render elements (e.g., a "Save" button).
  • When the initialData prop changes, you should update your internal representation of the original data and reset the dirty state.
Loading editor...
typescript