diff --git a/COMPONENT_INDEX.md b/COMPONENT_INDEX.md index 9b6b7acf..d85c882d 100644 --- a/COMPONENT_INDEX.md +++ b/COMPONENT_INDEX.md @@ -4753,15 +4753,19 @@ export interface TreeNode { ### Props -| Prop name | Kind | Reactive | Type | Default value | Description | -| :---------- | :--------------- | :------- | :------------------------------------------------------- | ---------------------- | --------------------------------------------------------------- | -| expandedIds | let | Yes | TreeNodeId[] | [] | Set the node ids to be expanded | -| selectedIds | let | Yes | TreeNodeId[] | [] | Set the node ids to be selected | -| activeId | let | Yes | TreeNodeId | "" | Set the current active node id
Only one node can be active | -| children | let | No | Array | [] | Provide an array of children nodes to render | -| size | let | No | "default" | "compact" | "default" | Specify the TreeView size | -| labelText | let | No | string | "" | Specify the label text | -| hideLabel | let | No | boolean | false | Set to `true` to visually hide the label text | +| Prop name | Kind | Reactive | Type | Default value | Description | +| :------------ | :-------------------- | :------- | :------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| expandedIds | let | Yes | TreeNodeId[] | [] | Set the node ids to be expanded | +| selectedIds | let | Yes | TreeNodeId[] | [] | Set the node ids to be selected | +| activeId | let | Yes | TreeNodeId | "" | Set the current active node id
Only one node can be active | +| children | let | No | Array | [] | Provide an array of children nodes to render | +| size | let | No | "default" | "compact" | "default" | Specify the TreeView size | +| labelText | let | No | string | "" | Specify the label text | +| hideLabel | let | No | boolean | false | Set to `true` to visually hide the label text | +| expandAll | function | No | () => void | () => { expandedIds = [...nodeIds]; } | Programmatically expand all nodes | +| collapseAll | function | No | () => void | () => { expandedIds = []; } | Programmatically collapse all nodes | +| expandNodes | function | No | (filterId?: (node: TreeNode) => boolean) => void | () => { expandedIds = nodes .filter((node) => !filterNode(node)) .map((node) => node.id); } | Programmatically expand a subset of nodes.
Expands all nodes if no argument is provided | +| collapseNodes | function | No | (filterId?: (node: TreeNode) => boolean) => void | () => { expandedIds = nodes .filter((node) => !filterNode(node)) .map((node) => node.id); } | Programmatically collapse a subset of nodes.
Collapses all nodes if no argument is provided | ### Slots diff --git a/docs/src/COMPONENT_API.json b/docs/src/COMPONENT_API.json index 7435dbd5..0d746ed7 100644 --- a/docs/src/COMPONENT_API.json +++ b/docs/src/COMPONENT_API.json @@ -13163,6 +13163,50 @@ "isFunctionDeclaration": false, "constant": false, "reactive": false + }, + { + "name": "expandAll", + "kind": "function", + "description": "Programmatically expand all nodes", + "type": "() => void", + "value": "() => { expandedIds = [...nodeIds]; }", + "isFunction": true, + "isFunctionDeclaration": true, + "constant": false, + "reactive": false + }, + { + "name": "collapseAll", + "kind": "function", + "description": "Programmatically collapse all nodes", + "type": "() => void", + "value": "() => { expandedIds = []; }", + "isFunction": true, + "isFunctionDeclaration": true, + "constant": false, + "reactive": false + }, + { + "name": "expandNodes", + "kind": "function", + "description": "Programmatically expand a subset of nodes.\nExpands all nodes if no argument is provided", + "type": "(filterId?: (node: TreeNode) => boolean) => void", + "value": "() => { expandedIds = nodes .filter((node) => !filterNode(node)) .map((node) => node.id); }", + "isFunction": true, + "isFunctionDeclaration": true, + "constant": false, + "reactive": false + }, + { + "name": "collapseNodes", + "kind": "function", + "description": "Programmatically collapse a subset of nodes.\nCollapses all nodes if no argument is provided", + "type": "(filterId?: (node: TreeNode) => boolean) => void", + "value": "() => { expandedIds = nodes .filter((node) => !filterNode(node)) .map((node) => node.id); }", + "isFunction": true, + "isFunctionDeclaration": true, + "constant": false, + "reactive": false } ], "slots": [ diff --git a/docs/src/pages/components/TreeView.svx b/docs/src/pages/components/TreeView.svx index 4cd34e29..daaf5205 100644 --- a/docs/src/pages/components/TreeView.svx +++ b/docs/src/pages/components/TreeView.svx @@ -45,4 +45,34 @@ Expanded nodes can be set using `expandedIds`. Initial multiple selected nodes can be set using `selectedIds`. - \ No newline at end of file + + +### Expand all nodes + +To programmatically expand all nodes, access the component instance using the [bind:this](https://svelte.dev/docs#bind_element) directive and invoke the `TreeView.expandAll()` method to expand all nodes. + + + +### Collapse all nodes + +Similarly, invoke `TreeView.collapseAll()` to collapse all nodes. + + + +### Expand a subset of nodes + +Use the `TreeView.expandNodes` method to expand only a subset of nodes. + +The method accepts an argument that takes a node and returns a boolean. + +If no argument is provided, all nodes will be expanded. + + + +### Collapse a subset of nodes + +Use the `TreeView.collapseNodes` method to collapse a subset of nodes. + +If no argument is provided, all nodes will be collapsed. + + \ No newline at end of file diff --git a/docs/src/pages/framed/TreeView/TreeViewCollapseAll.svelte b/docs/src/pages/framed/TreeView/TreeViewCollapseAll.svelte new file mode 100644 index 00000000..abbd09e0 --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewCollapseAll.svelte @@ -0,0 +1,63 @@ + + +
+ +
+ + + + diff --git a/docs/src/pages/framed/TreeView/TreeViewCollapseNodes.svelte b/docs/src/pages/framed/TreeView/TreeViewCollapseNodes.svelte new file mode 100644 index 00000000..69bda008 --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewCollapseNodes.svelte @@ -0,0 +1,71 @@ + + +
+ +
+ + + + diff --git a/docs/src/pages/framed/TreeView/TreeViewExpandAll.svelte b/docs/src/pages/framed/TreeView/TreeViewExpandAll.svelte new file mode 100644 index 00000000..ea10f4ac --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewExpandAll.svelte @@ -0,0 +1,61 @@ + + +
+ +
+ + + + diff --git a/docs/src/pages/framed/TreeView/TreeViewExpandNodes.svelte b/docs/src/pages/framed/TreeView/TreeViewExpandNodes.svelte new file mode 100644 index 00000000..0c1efeb3 --- /dev/null +++ b/docs/src/pages/framed/TreeView/TreeViewExpandNodes.svelte @@ -0,0 +1,67 @@ + + +
+ +
+ + + + diff --git a/src/TreeView/TreeView.svelte b/src/TreeView/TreeView.svelte index 699a4898..7e36da2e 100644 --- a/src/TreeView/TreeView.svelte +++ b/src/TreeView/TreeView.svelte @@ -44,6 +44,44 @@ /** Set to `true` to visually hide the label text */ export let hideLabel = false; + /** + * Programmatically expand all nodes + * @type {() => void} + */ + export function expandAll() { + expandedIds = [...nodeIds]; + } + + /** + * Programmatically collapse all nodes + * @type {() => void} + */ + export function collapseAll() { + expandedIds = []; + } + + /** + * Programmatically expand a subset of nodes. + * Expands all nodes if no argument is provided + * @type {(filterId?: (node: TreeNode) => boolean) => void} + */ + export function expandNodes(filterNode = (node) => false) { + expandedIds = nodes + .filter((node) => !filterNode(node)) + .map((node) => node.id); + } + + /** + * Programmatically collapse a subset of nodes. + * Collapses all nodes if no argument is provided + * @type {(filterId?: (node: TreeNode) => boolean) => void} + */ + export function collapseNodes(filterNode = (node) => true) { + expandedIds = nodes + .filter((node) => !filterNode(node)) + .map((node) => node.id); + } + import { createEventDispatcher, setContext, onMount } from "svelte"; import { writable } from "svelte/store"; import TreeViewNodeList from "./TreeViewNodeList.svelte"; @@ -105,6 +143,25 @@ } }); + /** + * @param {Array} children + */ + function traverse(children) { + let nodes = []; + + children.forEach((node) => { + nodes.push(node); + + if (Array.isArray(node.children)) { + nodes = [...nodes, ...traverse(node.children)]; + } + }); + + return nodes; + } + + $: nodes = traverse(children); + $: nodeIds = nodes.map((node) => node.id); $: activeNodeId.set(activeId); $: selectedNodeIds.set(selectedIds); $: expandedNodeIds.set(expandedIds); diff --git a/tests/TreeView.test.svelte b/tests/TreeView.test.svelte index 67308296..69e8e60a 100644 --- a/tests/TreeView.test.svelte +++ b/tests/TreeView.test.svelte @@ -3,6 +3,7 @@ import type { TreeNodeId } from "../types/TreeView/TreeView"; import Analytics16 from "carbon-icons-svelte/lib/Analytics16"; + let treeview: TreeView; let activeId: TreeNodeId = ""; let selectedIds = []; let expandedIds = [1]; @@ -46,9 +47,21 @@ children: [{ id: 15, text: "IBM API Connect", disabled: true }], }, ]; + + $: if (treeview) { + treeview.expandAll(); + treeview.expandNodes((node) => { + return node.id > 0; + }); + treeview.collapseAll(); + treeview.collapseNodes((node) => { + return node.disabled; + }); + } {} +> { + /** + * Programmatically expand all nodes + * @default () => { expandedIds = [...nodeIds]; } + */ + expandAll: () => void; + + /** + * Programmatically collapse all nodes + * @default () => { expandedIds = []; } + */ + collapseAll: () => void; + + /** + * Programmatically expand a subset of nodes. + * Expands all nodes if no argument is provided + * @default () => { expandedIds = nodes .filter((node) => !filterNode(node)) .map((node) => node.id); } + */ + expandNodes: (filterId?: (node: TreeNode) => boolean) => void; + + /** + * Programmatically collapse a subset of nodes. + * Collapses all nodes if no argument is provided + * @default () => { expandedIds = nodes .filter((node) => !filterNode(node)) .map((node) => node.id); } + */ + collapseNodes: (filterId?: (node: TreeNode) => boolean) => void; +}