Skip to content

Commit 92c26ea

Browse files
added treeview control
added treeview control Co-Authored-By: Nanddeep Nachan <[email protected]>
1 parent 0ac78d9 commit 92c26ea

20 files changed

+1570
-22
lines changed
12.7 KB
Loading
573 KB
Loading
10.6 KB
Loading
12.2 KB
Loading
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
## TreeView control
2+
3+
This graphical control allows to present a hierarchical view of information. Each tree item can have a number of subitems. This is often visualized by indentation in a list. An tree item can be expanded to reveal subitems (if exists), and collapsed to hide subitems.
4+
5+
Here is an example of the control in action:
6+
7+
![Tree View control](assets/TreeView-control.gif)
8+
9+
**With all possible options**
10+
11+
![Tree View control](assets/TreeView-all-possible-options.png)
12+
13+
**Without check boxes or when selection mode is 'None'**
14+
15+
![Tree View control](assets/TreeView-without-checkbox.png)
16+
17+
**Without check boxes, and selection mode is multiple**
18+
19+
![Tree View control](assets/TreeView-without-checkbox-selection-mode.png)
20+
21+
## How to use this control in your solutions
22+
23+
- Check that you installed the `@pnp/spfx-controls-react` dependency. Check out the [getting started](../../#getting-started) page for more information about installing the dependency.
24+
- Import the following modules to your component:
25+
26+
```TypeScript
27+
import { TreeView, ITreeItem } from "@pnp/spfx-controls-react/lib/TreeView";
28+
```
29+
30+
- Use the `TreeView` control in your code as follows:
31+
32+
```TypeScript
33+
<TreeView
34+
items={treeitems}
35+
defaultExpanded={false}
36+
selectionMode={TreeViewSelectionMode.Multiple}
37+
selectChildrenIfParentSelected={true}
38+
showCheckboxes={true}
39+
treeItemActionsDisplayMode={TreeItemActionsDisplayMode.ContextualMenu}
40+
defaultSelectedKeys=['key1', 'key2'],
41+
onSelect={this.onTreeItemSelect}
42+
onExpandCollapse={this.onTreeItemExpandCollapse}
43+
onRenderItem={this.renderCustomTreeItem} />
44+
```
45+
46+
- With the `onSelect` property you can capture the event of when the tree item in the TreeView has changed the selection:
47+
48+
```typescript
49+
private onTreeItemSelect(items: ITreeItem[]) {
50+
console.log("Items selected: ", items);
51+
}
52+
```
53+
54+
- With the `onExpandCollapse` property you can capture the event of when the tree item in the TreeView has expanded or collapsed:
55+
56+
```typescript
57+
private onTreeItemExpandCollapse(item: ITreeItem, isExpanded: boolean) {
58+
console.log((isExpanded ? "Item expanded: " : "Item collapsed: ") + item);
59+
}
60+
```
61+
62+
- Each tree item in the `treeitems` property is defined as `ITreeItem` as follows:
63+
64+
Interface `ITreeItem`
65+
66+
| Property | Type | Required | Description |
67+
|------------|-------------------|----------|------------------------------------------------------------------|
68+
| key | string | yes | The unique ID of the tree item. |
69+
| label | string | yes | Text displayed next to checkbox. |
70+
| subLabel | string | no | The sub label of the tree item. |
71+
| iconProps | IIconProps | no | Custom icon to be rendered before label. |
72+
| disabled | boolean | no | Specify if the tree item needs to be disabled. Default is false. |
73+
| selectable | boolean | no | Specify if the tree item can be selected. Default is true. |
74+
| data | any | no | Specify an additional data of the tree item. |
75+
| actions | ITreeItemAction[] | no | Specify list of actions for the tree item. |
76+
| children | ITreeItem[] | no | Specify list of child tree items. |
77+
78+
79+
Interface `ITreeItemAction`
80+
81+
Specifies the list of actions for the tree item.
82+
| Property | Type | Required | Description |
83+
|----------------------|--------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------|
84+
| id | string | yes | Unique id of the action. |
85+
| title | string | yes | Title of the action. |
86+
| iconProps | IIconProps | no | Name of the icon to be used to display action. |
87+
| hidden | boolean | no | Specify if the action is hidden. This could be used for instance when you want to invoke the action right after rendering. |
88+
| invokeActionOnRender | boolean | no | Specifies if you want to invoke the action on render. |
89+
| actionCallback | (currentTreeItem: ITreeItem) => void | yes | Method to be executed when action is fired. |
90+
91+
Enum `TreeItemActionsDisplayMode`
92+
93+
Specifies the display mode of the tree item action.
94+
| Value |
95+
|----------------|
96+
| Buttons |
97+
| ContextualMenu |
98+
99+
## Custom Rendering
100+
You can fully customize how tree items are rendered by providing the onRenderItem callback function and returning whatever JSX.Element you want.
101+
102+
For example, you can define your function in a tsx file like this:
103+
104+
```typescript
105+
import * as React from 'react';
106+
107+
export const renderCustomTreeItem = (item: ITreeItem): JSX.Element => {
108+
return (
109+
<span>
110+
<i className={"ms-Icon ms-Icon--" + item.iconProps.iconName} style={{paddingRight:'4px'}}/>
111+
{item.label}
112+
</span>
113+
);
114+
};
115+
```
116+
117+
## Implementation
118+
119+
The TreeView control can be configured with the following properties:
120+
121+
| Property | Type | Required | Description |
122+
|--------------------------------|----------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------|
123+
| 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). |
124+
| defaultExpanded | boolean | no | Specify if the tree items are displayed as expanded by default (defaults to false). |
125+
| selectionMode | enum | no | Specify the selection mode of tree view (defaults to Single selection). |
126+
| selectChildrenIfParentSelected | boolean | no | Specify if the childrens should be selected when parent item is selected (defaults to false). |
127+
| showCheckboxes | boolean | yes | Specify if the checkboxes should be displayed for selection. |
128+
| treeItemActionsDisplayMode | TreeItemActionsDisplayMode | no | Specify the display mode of the tree item actions. |
129+
| defaultSelectedKeys | string[] | no | Specify keys of items to be selected by default. |
130+
| onExpandCollapse | function | no | Defines a onExpandCollapse function to raise when the tree item has expanded or collapsed. |
131+
| onSelect | function | no | Captures the event of when the tree item selection has changed. |
132+
| onRenderItem | function | no | Optional callback to provide custom rendering of the item (default is simple text of item label and a checkbox for selection). |
133+
134+
Enum `TreeViewSelectionMode`
135+
136+
Specifies the selection mode of tree item.
137+
| Value |
138+
|----------|
139+
| Single |
140+
| Multiple |
141+
| None |
142+
143+
## Example of array of tree items used to render control as in 2nd screenshot
144+
145+
```typescript
146+
items: [
147+
{
148+
key: "R1",
149+
label: "Root",
150+
subLabel: "This is a sub label for node",
151+
iconProps: skypeCheckIcon,
152+
actions: [{
153+
title: "Get item",
154+
iconProps: {
155+
iconName: 'Warning',
156+
style: {
157+
color: 'salmon',
158+
},
159+
},
160+
id: "GetItem",
161+
actionCallback: async (treeItem: ITreeItem) => {
162+
console.log(treeItem);
163+
}
164+
}],
165+
children: [
166+
{
167+
key: "1",
168+
label: "Parent 1",
169+
selectable: false,
170+
children: [
171+
{
172+
key: "3",
173+
label: "Child 1",
174+
subLabel: "This is a sub label for node",
175+
actions: [{
176+
title:"Share",
177+
iconProps: {
178+
iconName: 'Share'
179+
},
180+
id: "GetItem",
181+
actionCallback: async (treeItem: ITreeItem) => {
182+
console.log(treeItem);
183+
}
184+
}],
185+
children: [
186+
{
187+
key: "gc1",
188+
label: "Grand Child 1",
189+
actions: [{
190+
title: "Get Grand Child item",
191+
iconProps: {
192+
iconName: 'Mail'
193+
},
194+
id: "GetItem",
195+
actionCallback: async (treeItem: ITreeItem) => {
196+
console.log(treeItem);
197+
}
198+
}]
199+
}
200+
]
201+
},
202+
{
203+
key: "4",
204+
label: "Child 2",
205+
iconProps: skypeCheckIcon
206+
}
207+
]
208+
},
209+
{
210+
key: "2",
211+
label: "Parent 2"
212+
},
213+
{
214+
key: "5",
215+
label: "Parent 3",
216+
disabled: true
217+
},
218+
{
219+
key: "6",
220+
label: "Parent 4",
221+
selectable: true
222+
}
223+
]
224+
},
225+
{
226+
key: "R2",
227+
label: "Root 2",
228+
children: [
229+
{
230+
key: "8",
231+
label: "Parent 5"
232+
}
233+
]
234+
}
235+
]
236+
```
237+

src/TreeView.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './controls/treeView/index';
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import * as React from 'react';
2+
import { CommandBarButton } from 'office-ui-fabric-react/lib/Button';
3+
import { IIconProps } from 'office-ui-fabric-react/lib/Icon';
4+
import { ITreeItemAction, IConcreteTreeItemActionProps } from './ITreeItemActions';
5+
import styles from './TreeView.module.scss';
6+
7+
/**
8+
* Renders the controls for Button TreeItem action component
9+
*/
10+
export default class ButtonTreeItemAction extends React.Component<IConcreteTreeItemActionProps> {
11+
12+
/**
13+
* componentWillMount lifecycle hook
14+
*/
15+
public componentWillMount(): void {
16+
this.checkForImmediateInvocations();
17+
}
18+
19+
/**
20+
* Prepares the command bar button
21+
*/
22+
private prepareCommandBarButton = (treeItemAction: ITreeItemAction): { name: string, text: string, iconProps: IIconProps, btnTitle: string } => {
23+
let name: string = treeItemAction.title;
24+
let text: string = treeItemAction.title;
25+
let iconProps: IIconProps = treeItemAction.iconProps;
26+
let btnTitle: string = treeItemAction.title;
27+
28+
return { name, text, iconProps, btnTitle };
29+
}
30+
31+
/**
32+
* Gets the action button styling
33+
*/
34+
private getTreeItemActionButtonStyle = (treeItemAction: ITreeItemAction): React.CSSProperties => {
35+
let result: React.CSSProperties = {
36+
backgroundColor: "transparent",
37+
height: "32px"
38+
};
39+
40+
return result;
41+
}
42+
43+
/**
44+
* Check if there are action to immediatly invoke
45+
*/
46+
private checkForImmediateInvocations() {
47+
const { treeItemActions } = this.props;
48+
49+
for (const action of treeItemActions) {
50+
if (action.invokeActionOnRender) {
51+
this.onActionExecute(action);
52+
}
53+
}
54+
}
55+
56+
/**
57+
* On action execution
58+
*/
59+
private onActionExecute = async (treeItemAction: ITreeItemAction) => {
60+
await treeItemAction.actionCallback(this.props.treeItem);
61+
this.props.treeItemActionCallback();
62+
}
63+
64+
/**
65+
* Default React render method
66+
*/
67+
public render(): React.ReactElement<IConcreteTreeItemActionProps> {
68+
const { treeItem, treeItemActions } = this.props;
69+
70+
// Check if there are actions to show
71+
const actionsToShow = treeItemActions.filter(a => !a.hidden);
72+
if (actionsToShow && actionsToShow.length === 0) {
73+
return null;
74+
}
75+
76+
return (
77+
<div>
78+
{
79+
treeItemActions &&
80+
treeItemActions.map(treeItemAction => {
81+
const { name, text, iconProps, btnTitle } = this.prepareCommandBarButton(treeItemAction);
82+
83+
return (
84+
treeItemAction.hidden ? (
85+
null
86+
) : (
87+
<div>
88+
<CommandBarButton split={true}
89+
onClick={() => { this.onActionExecute(treeItemAction); }}
90+
iconProps={iconProps}
91+
text={text}
92+
title={btnTitle}
93+
name={name}
94+
key={treeItem.key}
95+
className={styles.actionButton} />
96+
</div>
97+
)
98+
);
99+
})
100+
}
101+
</div>
102+
);
103+
}
104+
}

0 commit comments

Comments
 (0)