Skip to content

Commit 2cb535a

Browse files
committed
Fix to keep traversing tree, even if parent is selected. Potentially some children's keys are passed in as well to be default selected.
Added way more flexibility to decide when in the lifecycle the children of a selected item should be selected too.
1 parent e59fb52 commit 2cb535a

File tree

3 files changed

+60
-11
lines changed

3 files changed

+60
-11
lines changed

docs/documentation/docs/controls/TreeView.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import { TreeView, ITreeItem, TreeViewSelectionMode } from "@pnp/spfx-controls-r
3434
items={treeitems}
3535
defaultExpanded={false}
3636
selectionMode={TreeViewSelectionMode.Multiple}
37-
selectChildrenIfParentSelected={true}
37+
selectChildrenMode={SelectChildrenMode.Select | SelectChildrenMode.Unselect}
3838
showCheckboxes={true}
3939
treeItemActionsDisplayMode={TreeItemActionsDisplayMode.ContextualMenu}
4040
defaultSelectedKeys={['key1', 'key2']}
@@ -91,7 +91,8 @@ The `TreeView` control can be configured with the following properties:
9191
| items | ITreeItem[] | yes | An array of tree items to display. refer [example](#example-of-array-of-tree-items-used-to-render-control-as-in-first-screenshot). |
9292
| defaultExpanded | boolean | no | Specify if the tree items are displayed as expanded by default (defaults to false. |
9393
| selectionMode | enum | no | Specifies the selection mode of tree view (defaults to Single selection). |
94-
| selectChildrenIfParentSelected | boolean | no | Specifies if the childrens should be selected when parent item is selected (defaults to false). |
94+
| selectChildrenIfParentSelected | boolean | no | Specifies if the children should be selected when parent item is selected (defaults to false). __Deprecated__: prefer usage of `selectChildrenMode` for more flexibility. |
95+
| selectChildrenMode | SelectChildrenMode | no | Specifies if the children should be selected when parent item is selected (defaults to None). Flagged enum, values can be combined eg. `SelectChildrenMode.Select \| SelectChildrenMode.Unselect` |
9596
| showCheckboxes | boolean | yes | Specify if the checkboxes should be displayed for selection. |
9697
| treeItemActionsDisplayMode | TreeItemActionsDisplayMode | no | Specifies the display mode of the tree item actions. |
9798
| defaultSelectedKeys | string[] | no | Specifies keys of items to be selected by default. |
@@ -111,6 +112,19 @@ Specifies the selection mode of tree item.
111112
| Multiple |
112113
| None |
113114
115+
Enum `SelectChildrenMode`
116+
117+
Specifies when the children of a selected item need to be automatically selected.
118+
119+
| Value | Description |
120+
|----------|------------------------------------------------------------------|
121+
| None | Children are never selected |
122+
| Select | When selecting an item, its children are also selected |
123+
| Unselect | When unselecting an item, its children are also unselected |
124+
| Mount | When the component is mounted, all children of selected items are also selected |
125+
| Update | When the component receives new props, all children of selected items are also selected |
126+
| All | Shorthand for a combination of all of the above, same as `SelectChildrenMode.Select \| SelectChildrenMode.Unselect \| SelectChildrenMode.Mount \| SelectChildrenMode.Update` | |
127+
114128
Interface `ITreeItem`
115129
116130
Each tree item in the `treeitems` property is defined as `ITreeItem` as follows:

src/controls/treeView/ITreeViewProps.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ export enum TreeViewSelectionMode {
1010
None = 2
1111
}
1212

13+
export enum SelectChildrenMode {
14+
None = 0,
15+
Select = 1 << 0, // 0001
16+
Unselect = 1 << 1, // 0010
17+
Mount = 1 << 2, // 0100
18+
Update = 1 << 3, // 1000
19+
All = ~(~0 << 4) // 1111
20+
}
21+
1322
/**
1423
* TreeView properties interface
1524
*/
@@ -29,10 +38,16 @@ export interface ITreeViewProps {
2938
*/
3039
selectionMode?: TreeViewSelectionMode;
3140
/**
41+
* @deprecated Use selectChildrenMode instead
3242
* Specifies if the childrens should be selected when parent is selected.
3343
* By default this is set to false.
3444
*/
3545
selectChildrenIfParentSelected?: boolean;
46+
/**
47+
* Specifies if the childrens should be selected when parent is selected. Flagged enum, so values can be combined eg. SelectChildrenMode.Select | SelectChildrenMode.Unselect
48+
* By default this is set to None.
49+
*/
50+
selectChildrenMode?: SelectChildrenMode;
3651
/**
3752
* Specifies if the checkboxes should be displayed for selection.
3853
*/

src/controls/treeView/TreeView.tsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import styles from './TreeView.module.scss';
33
import uniqBy from 'lodash/uniqBy';
4-
import { ITreeViewProps, TreeViewSelectionMode } from './ITreeViewProps';
4+
import { ITreeViewProps, SelectChildrenMode, TreeViewSelectionMode } from './ITreeViewProps';
55
import { ITreeViewState } from './ITreeViewState';
66
import { ITreeItem } from './ITreeItem';
77
import TreeItem from './TreeItem';
@@ -68,6 +68,11 @@ export class TreeView extends React.Component<ITreeViewProps, ITreeViewState> {
6868
if (selectedChildren) {
6969
this.selectAllChildren(item, selectedItems);
7070
}
71+
else {
72+
if (item.children) {
73+
selectedItems.push(...this.getSelectedItems(item.children, selectedKeys, selectedChildren));
74+
}
75+
}
7176
}
7277
else {
7378
if (item.children) {
@@ -138,7 +143,7 @@ export class TreeView extends React.Component<ITreeViewProps, ITreeViewState> {
138143
// Add the checked term
139144
selectedItems.push(item);
140145

141-
if (this.props.selectChildrenIfParentSelected) {
146+
if (this.checkIfChildrenShouldBeSelected(SelectChildrenMode.Select)) {
142147
this.selectAllChildren(item, selectedItems);
143148
}
144149

@@ -163,7 +168,7 @@ export class TreeView extends React.Component<ITreeViewProps, ITreeViewState> {
163168
let unselectArray: string[] = [];
164169
unselectArray.push(item.key);
165170

166-
if (this.props.selectChildrenIfParentSelected) {
171+
if (this.checkIfChildrenShouldBeSelected(SelectChildrenMode.Unselect)) {
167172
this.unSelectChildren(item, unselectArray);
168173
}
169174

@@ -181,14 +186,30 @@ export class TreeView extends React.Component<ITreeViewProps, ITreeViewState> {
181186
}
182187
}
183188

189+
private checkIfChildrenShouldBeSelected(testMode: SelectChildrenMode) {
190+
let selectChildrenMode = SelectChildrenMode.None;
191+
if (this.props.selectChildrenMode) {
192+
selectChildrenMode = this.props.selectChildrenMode;
193+
}
194+
else {
195+
if (this.props.selectChildrenIfParentSelected) {
196+
selectChildrenMode = SelectChildrenMode.All;
197+
}
198+
}
199+
200+
if ((selectChildrenMode & testMode) === testMode) {
201+
return true;
202+
}
203+
return false;
204+
}
205+
184206
public componentDidMount() {
185207
const {
186208
items,
187-
defaultSelectedKeys,
188-
selectChildrenIfParentSelected
209+
defaultSelectedKeys
189210
} = this.props;
190211
if (defaultSelectedKeys) {
191-
const selectedItems = this.getSelectedItems(items, defaultSelectedKeys, selectChildrenIfParentSelected);
212+
const selectedItems = this.getSelectedItems(items, defaultSelectedKeys, this.checkIfChildrenShouldBeSelected(SelectChildrenMode.Mount));
192213
this.setState({
193214
activeItems: selectedItems
194215
});
@@ -198,11 +219,10 @@ export class TreeView extends React.Component<ITreeViewProps, ITreeViewState> {
198219
public componentWillReceiveProps(nextProps: ITreeViewProps): void {
199220
const {
200221
items,
201-
defaultSelectedKeys,
202-
selectChildrenIfParentSelected,
222+
defaultSelectedKeys
203223
} = nextProps;
204224
if (defaultSelectedKeys) {
205-
const selectedItems = !defaultSelectedKeys ? [] : this.getSelectedItems(items, defaultSelectedKeys, selectChildrenIfParentSelected);
225+
const selectedItems = this.getSelectedItems(items, defaultSelectedKeys, this.checkIfChildrenShouldBeSelected(SelectChildrenMode.Update));
206226
this.setState({
207227
activeItems: selectedItems
208228
});

0 commit comments

Comments
 (0)