Angular CdkTree expand all parent nodes

# Angular CDK Tree Expansion: Why Expanding a Node Doesn't Automatically Expand Parents

## Summary
- The Angular CDK Tree API requires manual recursive expansion of parent nodes when programmatically expanding a nested child node.  
- Default behavior (`MatTree.expand()`) only expands the target node, leaving ancestors unchanged.  
- Developers must implement custom logic to expand the entire parent chain.  

## Root Cause
- **Tree Component Independence**:  
  Angular CDK Tree treats nodes as independent entities for expansion state management.  
- **No Recursive Expansion Policy**:  
  The API intentionally avoids implicit parent expansion to maintain:  
  - Isolation of node state changes  
  - Flexibility for custom expansion workflows  
  - Avoidance of unintended bulk operations  

## Why This Happens in Real Systems
- Tree implementations often prioritize granular control over magic behavior:  
  - Complex state management when lazy-loading parent/child nodes  
  - Performance risks with automatic recursive expansion (especially in large trees)  
- Explicit parent expansion prevents:  
  - Undesired UI changes during targeted operations  
  - Unpredictable state propagation across nested levels  

## Real-World Impact
- **User Experience Degradation**:  
  Users see inactive pathways when child nodes expand without visible parent paths.  
- **State Inconsistencies**:  
  Partially expanded trees confuse users expecting hierarchical visibility.  
- **Increased Development Overhead**:  
  Engineers rebuild recursive logic instead of leveraging built-in methods.  

## Example Code
Improved Implementation:
```typescript
expandNodeWithParents(tree: MatTree<TreeNode>, node: MatTreeNode<TreeNode>): void {
  // Collect parents from leaf to root
  const parents: TreeNode[] = [];
  let current: MatTreeNode<TreeNode> | null = node;

  while (current) {
    parents.push(current.data);
    current = current.getParent();
  }

  // Expand from root to leaf
  parents.reverse().forEach(data => tree.expand(data));
}

How Senior Engineers Fix It

  1. Design Recursive Algorithms:
    Create helper functions that traverse upward to collect parents before expansion.
  2. Centralize Expansion Logic:
    Wrap tree interactions in a service to enforce consistency.
  3. Leverage Tree Control:
    Hook into TreeControl’s state management for unified behavior:

    expandAllParents(dataSource: MatTreeFlatDataSource, key: string) {
      const node = dataSource.data.find(n => n.key === key);
      const parents = this.treeControl.getParents(node);
      this.treeControl.expand(...parents);
    }
  4. Design Review:
    Challenge component APIs during implementation to avoid implicit assumptions.

Why Juniors Miss It

  • Component Assumption Gap:
    Expecting components to handle hierarchical relationships automatically.
  • API Literalism:
    Taking method names (expand()) at face value without considering hierarchy implications.
  • Recursion Avoidance:
    Hesitation to implement custom traversals for perceived common operations.
  • State Management Blindspots:
    Overlooking how isolated node operations affect overall UI state.