Skip to content

Commit d6a4f6c

Browse files
Add InitiallyExpandedSelector
1 parent 86786e7 commit d6a4f6c

2 files changed

Lines changed: 53 additions & 12 deletions

File tree

‎Components/FancyTreeTable.razor‎

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@
191191
[Parameter]
192192
public Func<TItem, bool>? HasChildrenSelector { get; set; }
193193

194+
[Parameter]
195+
public Func<TItem, bool>? InitiallyExpandedSelector { get; set; }
196+
194197
[Parameter]
195198
public FancyTableTexts? Texts { get; set; }
196199

@@ -349,6 +352,8 @@
349352
TreeNodeState<TItem> rootNode = BuildNode(item, depth: 0, parent: null, ancestors: []);
350353
RootNodes.Add(rootNode);
351354
}
355+
356+
RemoveObsoleteExpandedStates();
352357
}
353358

354359
private TreeNodeState<TItem> BuildNode(
@@ -366,13 +371,15 @@
366371
}
367372

368373
List<TItem> orderedChildren = ApplySiblingSort(childItems).ToList();
374+
bool hasChildren = HasChildrenSelector?.Invoke(item) ?? orderedChildren.Count > 0;
375+
bool isExpanded = GetOrInitializeExpandedState(item);
369376
TreeNodeState<TItem> node = new()
370377
{
371378
Item = item,
372379
Depth = depth,
373380
Parent = parent,
374-
HasChildren = HasChildrenSelector?.Invoke(item) ?? orderedChildren.Count > 0,
375-
IsExpanded = ExpandedStates.TryGetValue(item, out bool isExpanded) && isExpanded,
381+
HasChildren = hasChildren,
382+
IsExpanded = hasChildren && isExpanded,
376383
Children = []
377384
};
378385

@@ -504,31 +511,34 @@
504511

505512
private void ShowColumn(string key) => HiddenColumns.Remove(key);
506513

507-
private Task ToggleNodeAsync(TreeNodeState<TItem> node)
514+
private bool GetOrInitializeExpandedState(TItem item)
508515
{
509-
node.IsExpanded = !node.IsExpanded;
510-
if (node.IsExpanded)
516+
if (ExpandedStates.TryGetValue(item, out bool isExpanded))
511517
{
512-
ExpandedStates[node.Item] = true;
513-
}
514-
else
515-
{
516-
ExpandedStates.Remove(node.Item);
518+
return isExpanded;
517519
}
518520

521+
bool initialState = InitiallyExpandedSelector?.Invoke(item) ?? false;
522+
ExpandedStates[item] = initialState;
523+
return initialState;
524+
}
525+
526+
private Task ToggleNodeAsync(TreeNodeState<TItem> node)
527+
{
528+
node.IsExpanded = !node.IsExpanded;
529+
ExpandedStates[node.Item] = node.IsExpanded;
530+
519531
return Task.CompletedTask;
520532
}
521533

522534
public async Task ExpandAllAsync()
523535
{
524-
ExpandedStates.Clear();
525536
SetExpandedStateForAllNodes(expanded: true);
526537
await InvokeAsync(StateHasChanged);
527538
}
528539

529540
public async Task CollapseAllAsync()
530541
{
531-
ExpandedStates.Clear();
532542
SetExpandedStateForAllNodes(expanded: false);
533543
await InvokeAsync(StateHasChanged);
534544
}
@@ -639,10 +649,15 @@
639649
{
640650
ExpandedStates[node.Item] = true;
641651
}
652+
else
653+
{
654+
ExpandedStates[node.Item] = false;
655+
}
642656
}
643657
else
644658
{
645659
node.IsExpanded = false;
660+
ExpandedStates[node.Item] = false;
646661
}
647662

648663
foreach (TreeNodeState<TItem> child in node.Children)
@@ -651,6 +666,31 @@
651666
}
652667
}
653668

669+
private void RemoveObsoleteExpandedStates()
670+
{
671+
HashSet<TItem> activeItems = [];
672+
foreach (TreeNodeState<TItem> rootNode in RootNodes)
673+
{
674+
CollectNodeItems(rootNode, activeItems);
675+
}
676+
677+
List<TItem> obsoleteItems = ExpandedStates.Keys.Where(key => !activeItems.Contains(key)).ToList();
678+
foreach (TItem obsoleteItem in obsoleteItems)
679+
{
680+
ExpandedStates.Remove(obsoleteItem);
681+
}
682+
}
683+
684+
private static void CollectNodeItems(TreeNodeState<TItem> node, HashSet<TItem> activeItems)
685+
{
686+
activeItems.Add(node.Item);
687+
688+
foreach (TreeNodeState<TItem> child in node.Children)
689+
{
690+
CollectNodeItems(child, activeItems);
691+
}
692+
}
693+
654694
private TreeNodeStatistics GetTreeNodeStatistics()
655695
{
656696
TreeNodeStatistics stats = new();

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ https://www.nuget.org/packages/SoPro.FancyTable
102102
|-----------|------|-------------|
103103
| `ChildItemsSelector` | `Func<TItem, IEnumerable<TItem>?>` | Returns the child items for a given node (required) |
104104
| `HasChildrenSelector` | `Func<TItem, bool>?` | Optional optimization to indicate whether a node should render an expand/collapse toggle |
105+
| `InitiallyExpandedSelector` | `Func<TItem, bool>?` | Optional initial state provider used to seed each node's expand/collapse state the first time it appears |
105106
| `Texts` | `FancyTableTexts?` | Centralized overrides for built-in UI labels and summary text |
106107
| `TreeActionsTemplate` | `RenderFragment<FancyTreeTableContext<TItem>>?` | Renders custom tree-level actions such as expand/collapse all |
107108
| `TreeActionsContainerClass` | `string?` | Additional CSS classes for the tree actions wrapper |

0 commit comments

Comments
 (0)