Hone logo
Hone
Problems

Interactive Node Tree in Vue.js with TypeScript

This challenge focuses on building a dynamic, interactive node tree within a Vue.js application using TypeScript. You'll be creating a component that allows users to add, delete, and potentially move nodes within the tree structure, providing a practical exercise in component design, data management, and reactivity in Vue.js. This is a common pattern in applications dealing with hierarchical data, such as file explorers, organizational charts, or decision trees.

Problem Description

You are tasked with creating a Vue.js component called NodeTree that displays and allows manipulation of a tree structure represented as a nested array of objects. Each node object has the following properties:

  • id: A unique string identifier for the node.
  • name: A string representing the node's label.
  • children: An optional array of node objects representing the node's children. If a node has no children, this property should be omitted or an empty array.

The NodeTree component should:

  1. Display the tree: Render the tree structure visually, with nodes nested appropriately. A simple visual representation (e.g., using indentation or icons) is sufficient.
  2. Add a node: Provide a button or input field to add a new node as a child of the currently selected node. The new node should have a unique id and a name provided by the user. If no node is selected, the new node should be added as the root of the tree.
  3. Delete a node: Provide a mechanism (e.g., a button or context menu option) to delete a selected node. Deleting a node should also remove all its children.
  4. Node Selection: Allow the user to select a node. The selected node should be visually indicated (e.g., with a different background color or border). The "Add Node" functionality should operate on the currently selected node.
  5. Root Node Handling: Ensure that the root node(s) are handled correctly when adding or deleting nodes.

Expected Behavior:

  • The component should be reactive. Changes to the tree data (adding, deleting, or modifying nodes) should immediately update the displayed tree.
  • The component should handle empty trees gracefully.
  • The component should prevent adding nodes with duplicate IDs.
  • Deleting a node should not leave dangling references in the tree.

Examples

Example 1:

Input:
const treeData = [
  {
    id: 'root1',
    name: 'Root 1',
    children: [
      {
        id: 'child1',
        name: 'Child 1'
      },
      {
        id: 'child2',
        name: 'Child 2',
        children: [
          {
            id: 'grandchild1',
            name: 'Grandchild 1'
          }
        ]
      }
    ]
  }
];

Output:
A visual representation of the tree structure, with "Root 1" as the root, "Child 1" and "Child 2" as its children, and "Grandchild 1" as a child of "Child 2".  The user can select any node and add a new child to it.

Explanation: The component renders the nested structure, allowing for node selection and addition of new nodes as children of the selected node.

Example 2:

Input:
const treeData: any[] = [];

Output:
An empty tree view.  The "Add Node" button should still be functional, adding a new root node.

Explanation: The component handles the case where the tree is initially empty.

Example 3: (Edge Case - Deleting Root Node)

Input:
const treeData = [
  {
    id: 'root1',
    name: 'Root 1'
  }
];

Output:
An empty tree view.

Explanation: Deleting the root node should result in an empty tree.

Constraints

  • Data Structure: The tree data must be represented as a nested array of objects with the id, name, and children properties as described above.
  • Unique IDs: Ensure that all node IDs are unique within the entire tree. The component should prevent the addition of nodes with duplicate IDs.
  • Vue Version: Use Vue 3.
  • TypeScript: The solution must be written in TypeScript.
  • Performance: While not a primary focus, avoid excessively complex rendering logic that could lead to performance issues with large trees (e.g., > 100 nodes). Consider using Vue's reactivity system effectively.
  • UI: The visual representation of the tree can be simple (e.g., indentation, basic styling). Focus on the functionality rather than elaborate UI design.

Notes

  • Consider using Vue's v-for directive to recursively render the tree structure.
  • Use Vue's reactivity system (ref or reactive) to ensure that changes to the tree data are reflected in the UI.
  • Think about how to efficiently handle node selection and updating the UI when a node is selected.
  • You can use a simple library or custom logic to generate unique IDs for new nodes. Avoid using the same ID for multiple nodes.
  • Error handling (e.g., displaying messages when a node cannot be deleted due to constraints) is not required for this challenge, but is good practice.
Loading editor...
typescript