Expand To Collapse All Other Nodes In Angular 12

7 min read Sep 30, 2024
Expand To Collapse All Other Nodes In Angular 12

Expanding to Collapse All Other Nodes in Angular 12

Angular's hierarchical structures, often represented by trees or nested lists, offer a dynamic way to organize data. A common interaction requirement in such structures is the ability to expand a node while collapsing all others. This behavior is essential for creating user interfaces where users focus on a single branch of information at a time. In this article, we'll explore how to achieve this functionality in Angular 12 using a combination of template directives and component logic.

Understanding the Challenge

The core challenge lies in coordinating the expansion and collapse states across multiple nodes within a tree structure. Each node should respond independently to user interaction, ensuring that only the selected node remains expanded while all other nodes are collapsed.

The Solution: A Combined Approach

We'll use a combination of Angular's powerful features to implement this:

  1. Template Directives: Angular's @Directive decorator provides a way to create custom directives that modify the behavior of HTML elements. We'll create a directive to handle the expansion and collapse logic of individual nodes.

  2. Component Logic: Our component will manage the global state of all nodes, ensuring that only one node is expanded at a time.

Step-by-Step Implementation

1. Creating the Node Directive:

import { Directive, HostBinding, Input, HostListener } from '@angular/core';

@Directive({
  selector: '[appNode]' 
})
export class NodeDirective {

  @Input() expanded = false;

  @HostBinding('class.expanded')
  get isExpanded(): boolean {
    return this.expanded;
  }

  @HostListener('click')
  onClick() {
    // Emit event to notify the component about the node's click
  }
}

Explanation:

  • The appNode selector indicates that this directive will be applied to elements with the attribute appNode.
  • @Input() allows the directive to receive an expanded property from the parent component.
  • @HostBinding() binds the expanded property to the expanded CSS class on the element. This class will be applied when the node is expanded.
  • @HostListener() listens for click events on the element. When clicked, the onClick() method will be called.

2. Implementing the Component Logic:

import { Component } from '@angular/core';

@Component({
  selector: 'app-tree-view',
  templateUrl: './tree-view.component.html',
  styleUrls: ['./tree-view.component.css']
})
export class TreeViewComponent {

  nodes = [
    { id: 1, name: 'Node 1', expanded: false, children: [
      { id: 11, name: 'Node 1-1', expanded: false, children: [] }
    ] },
    { id: 2, name: 'Node 2', expanded: false, children: [
      { id: 21, name: 'Node 2-1', expanded: false, children: [] },
      { id: 22, name: 'Node 2-2', expanded: false, children: [] }
    ] },
  ];

  // Method to handle node click
  onNodeClick(node: any) {
    // Toggle the node's expansion state
    node.expanded = !node.expanded;

    // Collapse all other nodes
    this.nodes.forEach(n => {
      if (n.id !== node.id) {
        n.expanded = false;
      }
    });
  }
}

Explanation:

  • The nodes array represents the tree data structure.
  • The onNodeClick() method handles clicks on individual nodes.
  • When a node is clicked:
    • The node's expansion state is toggled.
    • All other nodes are collapsed.

3. Using the Directive and Component:

  • {{ node.name }}
    • {{ child.name }}

Explanation:

  • The appNode directive is applied to the <li> elements representing nodes.
  • The [expanded] binding passes the node's expanded state to the directive.
  • The (click) event emits a click event to the component's onNodeClick() method.

Example Usage

Let's consider a tree structure for displaying a file system:

  • {{ node.name }}
    • {{ child.name }}
      • {{ grandchild.name }}

In this example, clicking on a folder node will expand that folder and collapse all other folders. This behavior is essential for providing a focused user experience when navigating a file system.

Conclusion

By utilizing template directives and component logic, we've effectively implemented a solution for expanding a node while collapsing all others in Angular 12. This approach combines code reusability with component-level control over the global state of the tree structure, leading to a more streamlined and maintainable codebase.

This solution provides a foundation for implementing more complex interactions with hierarchical data structures in Angular applications. By extending this approach, you can introduce features like lazy loading of subtrees, dynamic node creation, and custom animations to enhance the user experience.

Latest Posts