Hone logo
Hone
Problems

Implementing a Dynamic Block Tree in Vue.js

This challenge focuses on building a reusable and interactive "block tree" component in Vue.js using TypeScript. A block tree is a hierarchical data structure commonly used in applications like content management systems, organizational charts, or file explorers, allowing users to visualize and manage nested content. The goal is to create a flexible component that can render arbitrary nested data and support basic interaction like expanding and collapsing nodes.

Problem Description

You are tasked with creating a Vue.js component, BlockTree, that renders a hierarchical structure of data. This component should be able to dynamically display nested data where each "block" or "node" can contain other blocks.

Key Requirements:

  1. Data Structure: The input data will be an array of objects. Each object represents a node and must have at least the following properties:

    • id: A unique identifier for the node.
    • name: The display name of the node.
    • children: An optional array of child nodes, following the same structure.
  2. Rendering: The component should recursively render the data. Each node should be displayed with its name.

  3. Expand/Collapse Functionality: Each node that has children should display an indicator (e.g., an icon) to toggle its visibility. Clicking this indicator should expand or collapse the node's children.

  4. State Management: The component should manage its own state regarding which nodes are expanded or collapsed. This state should be associated with each individual node.

  5. Reusability: The BlockTree component should be generic enough to accept any valid hierarchical data structure as defined above.

Expected Behavior:

  • Initially, only top-level nodes are visible.
  • Clicking an expand/collapse indicator on a parent node reveals or hides its direct children.
  • The tree should handle deeply nested structures correctly.
  • Nodes without children should not display an expand/collapse indicator.

Edge Cases:

  • An empty input array.
  • Nodes with empty children arrays.
  • Very deep nesting levels.

Examples

Example 1:

// Input Data Structure
const treeData = [
  {
    id: '1',
    name: 'Root 1',
    children: [
      { id: '1-1', name: 'Child 1.1' },
      {
        id: '1-2',
        name: 'Child 1.2',
        children: [
          { id: '1-2-1', name: 'Grandchild 1.2.1' },
        ],
      },
    ],
  },
  { id: '2', name: 'Root 2' },
];

Output: A rendered tree structure where:

  • "Root 1" is visible with an expand indicator.
  • Clicking "Root 1"'s indicator reveals "Child 1.1" and "Child 1.2".
  • "Child 1.1" has no indicator (no children).
  • "Child 1.2" is visible with an expand indicator.
  • Clicking "Child 1.2"'s indicator reveals "Grandchild 1.2.1".
  • "Grandchild 1.2.1" has no indicator.
  • "Root 2" is visible with no indicator.

Example 2:

// Input Data Structure
const emptyTreeData: Array<{ id: string; name: string; children?: any[] }> = [];

Output: An empty tree, no visible nodes or indicators.

Example 3:

// Input Data Structure
const complexTreeData = [
  {
    id: 'a',
    name: 'Level 1 A',
    children: [
      { id: 'a1', name: 'Level 2 A1', children: [] }, // Node with empty children array
      { id: 'a2', name: 'Level 2 A2' },
    ],
  },
  { id: 'b', name: 'Level 1 B' },
];

Output: A rendered tree where:

  • "Level 1 A" is visible with an indicator.
  • Clicking it reveals "Level 2 A1" and "Level 2 A2".
  • "Level 2 A1" should not have an indicator, even though it has an empty children array in its data.
  • "Level 2 A2" has no indicator.
  • "Level 1 B" has no indicator.

Constraints

  • The input treeData will be an array of objects conforming to the specified structure.
  • id and name will be strings.
  • children will be an optional array of objects of the same structure.
  • The depth of the tree can be up to 100 levels.
  • The total number of nodes in a tree can be up to 10,000.

Notes

  • Consider how you will manage the expanded/collapsed state for each node. You might need to augment the data structure or use a separate data structure to track this.
  • Think about the CSS styling needed to visually represent the hierarchy (indentation, icons). You'll be responsible for the basic structure and logic, not intricate styling.
  • A recursive component approach is likely to be very effective here.
  • The use of TypeScript generics could be beneficial for creating a truly reusable component.
Loading editor...
typescript