Skip to content

Commit f40eaf1

Browse files
committed
docs(tree-view): add filter nodes examples
1 parent 82627e3 commit f40eaf1

File tree

4 files changed

+338
-0
lines changed

4 files changed

+338
-0
lines changed

docs/src/pages/components/TreeView.svx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,21 @@ Use `TreeView.showNode` to expand, select, and focus a specific node.
113113
Convert flat data to a hierarchical structure using the `toHierarchy` utility.
114114

115115
<FileSource src="/framed/TreeView/TreeViewFlatArray" />
116+
117+
## Filter by text with search input
118+
119+
Combine a `Search` input with `filterTreeByText` to create an interactive searchable tree. Type to filter nodes by name (case-insensitive substring matching). By default, matching nodes and their ancestors are included to maintain valid tree structure.
120+
121+
<FileSource src="/framed/TreeView/TreeViewFilter" />
122+
123+
## Filter by ID
124+
125+
Use `filterTreeById` to filter nodes by their ID. Accepts either a single ID or an array of IDs. Click the buttons to filter by a single ID or multiple IDs. Matching nodes and their ancestors are included by default.
126+
127+
<FileSource src="/framed/TreeView/TreeViewFilterById" />
128+
129+
## Filter with custom predicate
130+
131+
Use `filterTreeNodes` with a predicate function to implement custom filtering logic. The example demonstrates filtering by file extension, filtering leaf nodes only, and using the `includeChildren` option to include all descendants of matching nodes. By default, matching nodes and their ancestors are included.
132+
133+
<FileSource src="/framed/TreeView/TreeViewFilterNodes" />
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<script>
2+
import { filterTreeByText, Search, TreeView } from "carbon-components-svelte";
3+
4+
const allNodes = [
5+
{
6+
id: "1",
7+
text: "Documents",
8+
nodes: [
9+
{
10+
id: "1-1",
11+
text: "Work",
12+
nodes: [
13+
{ id: "1-1-1", text: "Report.docx" },
14+
{ id: "1-1-2", text: "Presentation.pptx" },
15+
{ id: "1-1-3", text: "Budget.xlsx" },
16+
{ id: "1-1-4", text: "Meeting Notes.txt" },
17+
],
18+
},
19+
{
20+
id: "1-2",
21+
text: "Personal",
22+
nodes: [
23+
{ id: "1-2-1", text: "Resume.pdf" },
24+
{ id: "1-2-2", text: "Cover Letter.pdf" },
25+
{ id: "1-2-3", text: "Portfolio.pdf" },
26+
],
27+
},
28+
{
29+
id: "1-3",
30+
text: "Projects",
31+
nodes: [
32+
{
33+
id: "1-3-1",
34+
text: "Website",
35+
nodes: [
36+
{ id: "1-3-1-1", text: "index.html" },
37+
{ id: "1-3-1-2", text: "styles.css" },
38+
{ id: "1-3-1-3", text: "script.js" },
39+
],
40+
},
41+
{
42+
id: "1-3-2",
43+
text: "App",
44+
nodes: [
45+
{ id: "1-3-2-1", text: "main.py" },
46+
{ id: "1-3-2-2", text: "config.json" },
47+
],
48+
},
49+
],
50+
},
51+
],
52+
},
53+
{
54+
id: "2",
55+
text: "Pictures",
56+
nodes: [
57+
{ id: "2-1", text: "Vacation.jpg" },
58+
{ id: "2-2", text: "Family.jpg" },
59+
{ id: "2-3", text: "Birthday.png" },
60+
],
61+
},
62+
{
63+
id: "3",
64+
text: "Music",
65+
nodes: [
66+
{
67+
id: "3-1",
68+
text: "Rock",
69+
nodes: [
70+
{ id: "3-1-1", text: "Song1.mp3" },
71+
{ id: "3-1-2", text: "Song2.mp3" },
72+
],
73+
},
74+
{
75+
id: "3-2",
76+
text: "Jazz",
77+
nodes: [
78+
{ id: "3-2-1", text: "Song3.mp3" },
79+
{ id: "3-2-2", text: "Song4.mp3" },
80+
],
81+
},
82+
{
83+
id: "3-3",
84+
text: "Classical",
85+
nodes: [{ id: "3-3-1", text: "Symphony.mp3" }],
86+
},
87+
],
88+
},
89+
];
90+
91+
let searchValue = "";
92+
let expandedIds = [];
93+
94+
$: filteredNodes =
95+
searchValue.trim() === ""
96+
? allNodes
97+
: filterTreeByText(allNodes, searchValue);
98+
99+
$: if (searchValue.trim() !== "" && filteredNodes.length > 0) {
100+
const extractIds = (nodes) => {
101+
const ids = [];
102+
for (const node of nodes) {
103+
ids.push(node.id);
104+
if (node.nodes) {
105+
ids.push(...extractIds(node.nodes));
106+
}
107+
}
108+
return ids;
109+
};
110+
expandedIds = extractIds(filteredNodes);
111+
} else {
112+
expandedIds = [];
113+
}
114+
</script>
115+
116+
<Search size="sm" placeholder="Search tree nodes..." bind:value={searchValue} />
117+
118+
<div style:margin-top="var(--cds-layout-01)">
119+
{#if filteredNodes.length > 0}
120+
<TreeView labelText="File System" nodes={filteredNodes} {expandedIds} />
121+
{:else}
122+
No matching nodes found for "{searchValue}"
123+
{/if}
124+
</div>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<script>
2+
import {
3+
Button,
4+
ButtonSet,
5+
filterTreeById,
6+
TreeView,
7+
} from "carbon-components-svelte";
8+
9+
const allNodes = [
10+
{
11+
id: "1",
12+
text: "Documents",
13+
nodes: [
14+
{
15+
id: "1-1",
16+
text: "Work",
17+
nodes: [
18+
{ id: "1-1-1", text: "Report.docx" },
19+
{ id: "1-1-2", text: "Presentation.pptx" },
20+
{ id: "1-1-3", text: "Budget.xlsx" },
21+
],
22+
},
23+
{
24+
id: "1-2",
25+
text: "Personal",
26+
nodes: [
27+
{ id: "1-2-1", text: "Resume.pdf" },
28+
{ id: "1-2-2", text: "Cover Letter.pdf" },
29+
],
30+
},
31+
],
32+
},
33+
{
34+
id: "2",
35+
text: "Pictures",
36+
nodes: [
37+
{ id: "2-1", text: "Vacation.jpg" },
38+
{ id: "2-2", text: "Family.jpg" },
39+
],
40+
},
41+
{
42+
id: "3",
43+
text: "Music",
44+
nodes: [
45+
{
46+
id: "3-1",
47+
text: "Rock",
48+
nodes: [
49+
{ id: "3-1-1", text: "Song1.mp3" },
50+
{ id: "3-1-2", text: "Song2.mp3" },
51+
],
52+
},
53+
],
54+
},
55+
];
56+
57+
let filteredNodes = allNodes;
58+
let expandedIds = [];
59+
60+
function filterBySingleId() {
61+
filteredNodes = filterTreeById(allNodes, "1-1-1");
62+
expandedIds = ["1", "1-1", "1-1-1"];
63+
}
64+
65+
function filterByMultipleIds() {
66+
filteredNodes = filterTreeById(allNodes, ["1-1-1", "1-2-1", "2-1"]);
67+
expandedIds = ["1", "1-1", "1-1-1", "1-2", "1-2-1", "2", "2-1"];
68+
}
69+
70+
function resetFilter() {
71+
filteredNodes = allNodes;
72+
expandedIds = [];
73+
}
74+
</script>
75+
76+
<ButtonSet style="margin-bottom: var(--cds-layout-01)">
77+
<Button size="sm" on:click={filterBySingleId}>Filter single ID</Button>
78+
<Button size="sm" on:click={filterByMultipleIds}>Filter multiple IDs</Button>
79+
<Button size="sm" kind="tertiary" on:click={resetFilter}>Reset</Button>
80+
</ButtonSet>
81+
82+
<TreeView labelText="File System" nodes={filteredNodes} {expandedIds} />
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<script>
2+
import {
3+
Button,
4+
ButtonSet,
5+
filterTreeNodes,
6+
TreeView,
7+
} from "carbon-components-svelte";
8+
9+
const allNodes = [
10+
{
11+
id: "1",
12+
text: "Documents",
13+
nodes: [
14+
{
15+
id: "1-1",
16+
text: "Work",
17+
nodes: [
18+
{ id: "1-1-1", text: "Report.docx" },
19+
{ id: "1-1-2", text: "Presentation.pptx" },
20+
{ id: "1-1-3", text: "Budget.xlsx" },
21+
],
22+
},
23+
{
24+
id: "1-2",
25+
text: "Personal",
26+
nodes: [
27+
{ id: "1-2-1", text: "Resume.pdf" },
28+
{ id: "1-2-2", text: "Cover Letter.pdf" },
29+
],
30+
},
31+
],
32+
},
33+
{
34+
id: "2",
35+
text: "Pictures",
36+
nodes: [
37+
{ id: "2-1", text: "Vacation.jpg" },
38+
{ id: "2-2", text: "Family.jpg" },
39+
],
40+
},
41+
{
42+
id: "3",
43+
text: "Music",
44+
nodes: [
45+
{
46+
id: "3-1",
47+
text: "Rock",
48+
nodes: [
49+
{ id: "3-1-1", text: "Song1.mp3" },
50+
{ id: "3-1-2", text: "Song2.mp3" },
51+
],
52+
},
53+
],
54+
},
55+
];
56+
57+
let filteredNodes = allNodes;
58+
let expandedIds = [];
59+
60+
function filterByExtension() {
61+
filteredNodes = filterTreeNodes(
62+
allNodes,
63+
(node) => node.text?.endsWith(".pdf") || node.text?.endsWith(".docx"),
64+
);
65+
expandedIds = ["1", "1-1", "1-1-1", "1-2", "1-2-1"];
66+
}
67+
68+
function filterLeafNodes() {
69+
filteredNodes = filterTreeNodes(
70+
allNodes,
71+
(node) => !node.nodes || node.nodes.length === 0,
72+
);
73+
expandedIds = [
74+
"1",
75+
"1-1",
76+
"1-1-1",
77+
"1-1-2",
78+
"1-1-3",
79+
"1-2",
80+
"1-2-1",
81+
"1-2-2",
82+
"2",
83+
"2-1",
84+
"2-2",
85+
"3",
86+
"3-1",
87+
"3-1-1",
88+
"3-1-2",
89+
];
90+
}
91+
92+
function filterWithChildren() {
93+
filteredNodes = filterTreeNodes(allNodes, (node) => node.id === "1-1", {
94+
includeChildren: true,
95+
});
96+
expandedIds = ["1", "1-1", "1-1-1", "1-1-2", "1-1-3"];
97+
}
98+
99+
function resetFilter() {
100+
filteredNodes = allNodes;
101+
expandedIds = [];
102+
}
103+
</script>
104+
105+
<ButtonSet style="margin-bottom: var(--cds-layout-01)">
106+
<Button size="sm" on:click={filterByExtension}>
107+
Filter by extension (.pdf, .docx)
108+
</Button>
109+
<Button size="sm" on:click={filterLeafNodes}>Filter leaf nodes</Button>
110+
<Button size="sm" on:click={filterWithChildren}>Filter with children</Button>
111+
<Button size="sm" kind="tertiary" on:click={resetFilter}>Reset</Button>
112+
</ButtonSet>
113+
114+
<TreeView labelText="File System" nodes={filteredNodes} {expandedIds} />

0 commit comments

Comments
 (0)