playbook_ui 12.26.1.pre.alpha.play716popoverkitcloseonclickissue833 → 12.26.1.pre.alpha.railsmultilevelimprovements835
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_card/docs/_card_background.jsx +5 -4
- data/app/pb_kits/playbook/pb_date_year_stacked/date_year_stacked.test.js +6 -3
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_full_height.jsx +8 -4
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_full_height_placement.jsx +8 -4
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_scrollable.jsx +4 -2
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_status.jsx +1 -1
- data/app/pb_kits/playbook/pb_filter/filter.test.js +6 -3
- data/app/pb_kits/playbook/pb_form_group/form_group.test.js +2 -1
- data/app/pb_kits/playbook/pb_gauge/docs/_gauge_complex.jsx +1 -1
- data/app/pb_kits/playbook/pb_home_address_street/home_adress_street.test.js +1 -1
- data/app/pb_kits/playbook/pb_icon/icon.test.js +9 -9
- data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.test.js +8 -8
- data/app/pb_kits/playbook/pb_icon_value/icon_value.test.js +5 -5
- data/app/pb_kits/playbook/pb_layout/layout.test.js +8 -4
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +163 -123
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.html.erb +14 -6
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +8 -4
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.md +1 -1
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +14 -7
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.jsx +1 -1
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_complete_data.html.erb +73 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_complete_data.jsx +87 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_form.html.erb +72 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.html.erb +7 -3
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +6 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.jsx +2 -1
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_default.jsx +2 -1
- data/app/pb_kits/playbook/pb_popover/_popover.tsx +3 -5
- data/app/pb_kits/playbook/pb_popover/index.ts +2 -5
- data/app/pb_kits/playbook/pb_popover/popover.test.js +6 -6
- data/app/pb_kits/playbook/pb_selectable_list/selectable_list.test.js +4 -2
- data/dist/playbook-rails.js +5 -5
- data/lib/playbook/forms/builder/multi_level_select_field.rb +12 -0
- data/lib/playbook/forms/builder.rb +1 -0
- data/lib/playbook/version.rb +1 -1
- metadata +5 -1
@@ -1,12 +1,12 @@
|
|
1
|
-
import React, { useState, useEffect, useRef } from "react"
|
2
|
-
import classnames from "classnames"
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import FormPill from "../pb_form_pill/_form_pill"
|
8
|
-
import CircleIconButton from "../pb_circle_icon_button/_circle_icon_button"
|
9
|
-
import { cloneDeep } from "lodash"
|
1
|
+
import React, { useState, useEffect, useRef } from "react"
|
2
|
+
import classnames from "classnames"
|
3
|
+
import { globalProps, GlobalProps } from "../utilities/globalProps"
|
4
|
+
import { buildAriaProps, buildCss, buildDataProps } from "../utilities/props"
|
5
|
+
import Checkbox from "../pb_checkbox/_checkbox"
|
6
|
+
import Icon from "../pb_icon/_icon"
|
7
|
+
import FormPill from "../pb_form_pill/_form_pill"
|
8
|
+
import CircleIconButton from "../pb_circle_icon_button/_circle_icon_button"
|
9
|
+
import { cloneDeep } from "lodash"
|
10
10
|
|
11
11
|
import {
|
12
12
|
getAncestorsOfUnchecked,
|
@@ -15,17 +15,19 @@ import {
|
|
15
15
|
getCheckedItems,
|
16
16
|
getDefaultCheckedItems,
|
17
17
|
recursiveCheckParent,
|
18
|
-
} from "./_helper_functions"
|
18
|
+
} from "./_helper_functions"
|
19
19
|
|
20
20
|
type MultiLevelSelectProps = {
|
21
|
-
aria?: { [key: string]: string }
|
22
|
-
className?: string
|
23
|
-
data?: { [key: string]: string }
|
24
|
-
id?: string
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
aria?: { [key: string]: string }
|
22
|
+
className?: string
|
23
|
+
data?: { [key: string]: string }
|
24
|
+
id?: string
|
25
|
+
name?: string
|
26
|
+
returnCompleteData?: boolean
|
27
|
+
returnAllSelected?: boolean
|
28
|
+
treeData?: { [key: string]: string }[]
|
29
|
+
onSelect?: (prop: { [key: string]: any }) => void
|
30
|
+
} & GlobalProps
|
29
31
|
|
30
32
|
const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
31
33
|
const {
|
@@ -33,71 +35,106 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
33
35
|
className,
|
34
36
|
data = {},
|
35
37
|
id,
|
38
|
+
name,
|
36
39
|
returnAllSelected = false,
|
40
|
+
returnCompleteData = false,
|
37
41
|
treeData,
|
38
42
|
onSelect = () => {},
|
39
|
-
} = props
|
43
|
+
} = props
|
40
44
|
|
41
|
-
const ariaProps = buildAriaProps(aria)
|
42
|
-
const dataProps = buildDataProps(data)
|
45
|
+
const ariaProps = buildAriaProps(aria)
|
46
|
+
const dataProps = buildDataProps(data)
|
43
47
|
const classes = classnames(
|
44
48
|
buildCss("pb_multi_level_select"),
|
45
49
|
globalProps(props),
|
46
50
|
className
|
47
|
-
)
|
51
|
+
)
|
52
|
+
|
53
|
+
const dropdownRef = useRef(null)
|
48
54
|
|
49
|
-
const dropdownRef = useRef(null);
|
50
55
|
|
51
56
|
//state for expanded property
|
52
|
-
const [expanded, setExpanded] = useState([])
|
57
|
+
const [expanded, setExpanded] = useState([])
|
53
58
|
//state for whether dropdown is open or closed
|
54
|
-
const [isClosed, setIsClosed] = useState(true)
|
59
|
+
const [isClosed, setIsClosed] = useState(true)
|
55
60
|
//state from onchange for textinput, to use for filtering to create typeahead
|
56
|
-
const [filterItem, setFilterItem] = useState("")
|
61
|
+
const [filterItem, setFilterItem] = useState("")
|
57
62
|
//this is essentially the return that the user will get when they use the kit
|
58
|
-
const [returnedArray, setReturnedArray] = useState([])
|
63
|
+
const [returnedArray, setReturnedArray] = useState([])
|
59
64
|
//formattedData with checked and parent_id added
|
60
|
-
const [formattedData, setFormattedData] = useState([])
|
65
|
+
const [formattedData, setFormattedData] = useState([])
|
61
66
|
//state for return for default
|
62
|
-
const [defaultReturn, setDefaultReturn] = useState([])
|
67
|
+
const [defaultReturn, setDefaultReturn] = useState([])
|
68
|
+
|
69
|
+
const [formattedReturn, setFormattedReturn] = useState([])
|
70
|
+
|
71
|
+
const getSelectedIds = (selectedData: { [key: string]: any }[]) => {
|
72
|
+
return selectedData.map((item) => item.id)
|
73
|
+
}
|
74
|
+
|
75
|
+
const getValues = () => {
|
76
|
+
if (returnCompleteData) {
|
77
|
+
if (returnAllSelected) {
|
78
|
+
return setFormattedReturn(returnedArray)
|
79
|
+
} else {
|
80
|
+
return setFormattedReturn(defaultReturn)
|
81
|
+
}
|
82
|
+
} else {
|
83
|
+
if (returnAllSelected) {
|
84
|
+
setFormattedReturn(getSelectedIds(returnedArray))
|
85
|
+
} else {
|
86
|
+
setFormattedReturn(getSelectedIds(defaultReturn))
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
63
91
|
|
64
92
|
useEffect(() => {
|
65
|
-
|
66
|
-
}, [
|
93
|
+
getValues()
|
94
|
+
}, [returnedArray, defaultReturn])
|
95
|
+
|
96
|
+
useEffect(() => {
|
97
|
+
onSelect(formattedReturn)
|
98
|
+
}, [formattedReturn])
|
99
|
+
|
100
|
+
useEffect(() => {
|
101
|
+
setFormattedData(addCheckedAndParentProperty(treeData))
|
102
|
+
}, [treeData])
|
103
|
+
|
67
104
|
|
68
105
|
useEffect(() => {
|
69
106
|
if (returnAllSelected) {
|
70
|
-
setReturnedArray(getCheckedItems(formattedData))
|
107
|
+
setReturnedArray(getCheckedItems(formattedData))
|
71
108
|
} else {
|
72
|
-
setDefaultReturn(getDefaultCheckedItems(formattedData))
|
109
|
+
setDefaultReturn(getDefaultCheckedItems(formattedData))
|
73
110
|
}
|
74
|
-
}, [formattedData])
|
111
|
+
}, [formattedData])
|
75
112
|
|
76
113
|
useEffect(() => {
|
77
114
|
// Function to handle clicks outside the dropdown
|
78
115
|
const handleClickOutside = (event: any) => {
|
79
116
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
80
|
-
setIsClosed(true)
|
117
|
+
setIsClosed(true)
|
81
118
|
}
|
82
|
-
}
|
119
|
+
}
|
83
120
|
// Attach the event listener
|
84
|
-
window.addEventListener("click", handleClickOutside)
|
121
|
+
window.addEventListener("click", handleClickOutside)
|
85
122
|
// Clean up the event listener on unmount
|
86
123
|
return () => {
|
87
|
-
window.removeEventListener("click", handleClickOutside)
|
88
|
-
}
|
89
|
-
}, [])
|
124
|
+
window.removeEventListener("click", handleClickOutside)
|
125
|
+
}
|
126
|
+
}, [])
|
90
127
|
|
91
128
|
const modifyRecursive = (tree: { [key: string]: any }[], check: boolean) => {
|
92
129
|
if (!Array.isArray(tree)) {
|
93
|
-
return
|
130
|
+
return
|
94
131
|
}
|
95
132
|
return tree.map((item: { [key: string]: any }) => {
|
96
|
-
item.checked = check
|
97
|
-
item.children = modifyRecursive(item.children, check)
|
98
|
-
return item
|
99
|
-
})
|
100
|
-
}
|
133
|
+
item.checked = check
|
134
|
+
item.children = modifyRecursive(item.children, check)
|
135
|
+
return item
|
136
|
+
})
|
137
|
+
}
|
101
138
|
|
102
139
|
//iterate over tree, find item and set checked or unchecked
|
103
140
|
const modifyValue = (
|
@@ -106,48 +143,48 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
106
143
|
check: boolean
|
107
144
|
) => {
|
108
145
|
if (!Array.isArray(tree)) {
|
109
|
-
return
|
146
|
+
return
|
110
147
|
}
|
111
148
|
return tree.map((item: any) => {
|
112
|
-
if (item.id != id) item.children = modifyValue(id, item.children, check)
|
149
|
+
if (item.id != id) item.children = modifyValue(id, item.children, check)
|
113
150
|
else {
|
114
|
-
item.checked = check
|
115
|
-
item.children = modifyRecursive(item.children, check)
|
151
|
+
item.checked = check
|
152
|
+
item.children = modifyRecursive(item.children, check)
|
116
153
|
}
|
117
154
|
|
118
|
-
return item
|
119
|
-
})
|
120
|
-
}
|
155
|
+
return item
|
156
|
+
})
|
157
|
+
}
|
121
158
|
|
122
159
|
//clone tree, check items + children
|
123
160
|
const checkItem = (item: { [key: string]: any }) => {
|
124
|
-
const tree = cloneDeep(formattedData)
|
161
|
+
const tree = cloneDeep(formattedData)
|
125
162
|
if (returnAllSelected) {
|
126
|
-
return modifyValue(item.id, tree, true)
|
163
|
+
return modifyValue(item.id, tree, true)
|
127
164
|
} else {
|
128
|
-
const checkedTree = modifyValue(item.id, tree, true)
|
129
|
-
return recursiveCheckParent(item, checkedTree)
|
165
|
+
const checkedTree = modifyValue(item.id, tree, true)
|
166
|
+
return recursiveCheckParent(item, checkedTree)
|
130
167
|
}
|
131
|
-
}
|
168
|
+
}
|
132
169
|
|
133
170
|
//clone tree, uncheck items + children
|
134
171
|
const unCheckItem = (item: { [key: string]: any }) => {
|
135
|
-
const tree = cloneDeep(formattedData)
|
172
|
+
const tree = cloneDeep(formattedData)
|
136
173
|
if (returnAllSelected) {
|
137
|
-
return modifyValue(item.id, tree, false)
|
174
|
+
return modifyValue(item.id, tree, false)
|
138
175
|
} else {
|
139
|
-
const uncheckedTree = modifyValue(item.id, tree, false)
|
140
|
-
return getAncestorsOfUnchecked(uncheckedTree, item)
|
176
|
+
const uncheckedTree = modifyValue(item.id, tree, false)
|
177
|
+
return getAncestorsOfUnchecked(uncheckedTree, item)
|
141
178
|
}
|
142
|
-
}
|
179
|
+
}
|
143
180
|
|
144
181
|
//setformattedData with proper properties
|
145
182
|
const changeItem = (item: { [key: string]: any }, check: boolean) => {
|
146
|
-
const tree = check ? checkItem(item) : unCheckItem(item)
|
147
|
-
setFormattedData(tree)
|
183
|
+
const tree = check ? checkItem(item) : unCheckItem(item)
|
184
|
+
setFormattedData(tree)
|
148
185
|
|
149
|
-
return tree
|
150
|
-
}
|
186
|
+
return tree
|
187
|
+
}
|
151
188
|
|
152
189
|
//function to map over data and add parent_id + depth property to each item
|
153
190
|
const addCheckedAndParentProperty = (
|
@@ -156,87 +193,86 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
156
193
|
depth: number = 0
|
157
194
|
) => {
|
158
195
|
if (!Array.isArray(treeData)) {
|
159
|
-
return
|
196
|
+
return
|
160
197
|
}
|
161
198
|
return treeData.map((item: { [key: string]: any } | any) => {
|
162
199
|
const newItem = {
|
163
200
|
...item,
|
164
201
|
parent_id,
|
165
202
|
depth,
|
166
|
-
}
|
203
|
+
}
|
167
204
|
if (newItem.children && newItem.children.length > 0) {
|
168
205
|
const children =
|
169
206
|
item.checked && !returnAllSelected
|
170
207
|
? modifyRecursive(item.children, true)
|
171
|
-
: item.children
|
208
|
+
: item.children
|
172
209
|
newItem.children = addCheckedAndParentProperty(
|
173
210
|
children,
|
174
211
|
newItem.id,
|
175
212
|
depth + 1
|
176
|
-
)
|
213
|
+
)
|
177
214
|
}
|
178
|
-
return newItem
|
179
|
-
})
|
180
|
-
}
|
215
|
+
return newItem
|
216
|
+
})
|
217
|
+
}
|
181
218
|
|
182
219
|
//click event for x on form pill
|
183
220
|
const handlePillClose = (event: any, clickedItem: { [key: string]: any }) => {
|
184
221
|
// prevents the dropdown from closing when clicking on the pill
|
185
|
-
event.stopPropagation()
|
186
|
-
const updatedTree = changeItem(clickedItem, false)
|
222
|
+
event.stopPropagation()
|
223
|
+
const updatedTree = changeItem(clickedItem, false)
|
187
224
|
//logic for removing items from returnArray or defaultReturn when pills clicked
|
188
225
|
if (returnAllSelected) {
|
189
|
-
onSelect(getCheckedItems(updatedTree))
|
226
|
+
onSelect(getCheckedItems(updatedTree))
|
190
227
|
} else {
|
191
|
-
onSelect(getDefaultCheckedItems(updatedTree))
|
228
|
+
onSelect(getDefaultCheckedItems(updatedTree))
|
192
229
|
}
|
193
|
-
}
|
230
|
+
}
|
194
231
|
|
195
232
|
//handle click on input wrapper(entire div with pills, typeahead, etc) so it doesn't close when input or form pill is clicked
|
196
233
|
const handleInputWrapperClick = (e: any) => {
|
197
|
-
e.stopPropagation()
|
234
|
+
e.stopPropagation()
|
198
235
|
if (
|
199
236
|
e.target.id === "multiselect_input" ||
|
200
237
|
e.target.classList.contains("pb_form_pill_tag")
|
201
238
|
) {
|
202
|
-
return
|
239
|
+
return
|
203
240
|
}
|
204
|
-
setIsClosed(!isClosed)
|
205
|
-
}
|
241
|
+
setIsClosed(!isClosed)
|
242
|
+
}
|
206
243
|
|
207
244
|
//Main function to handle any click inside dropdown
|
208
245
|
const handledropdownItemClick = (e: any, check: boolean) => {
|
209
|
-
const clickedItem = e.target.parentNode.id
|
246
|
+
const clickedItem = e.target.parentNode.id
|
210
247
|
//setting filterItem to "" will clear textinput and clear typeahead
|
211
|
-
setFilterItem("")
|
248
|
+
setFilterItem("")
|
212
249
|
|
213
|
-
const filtered = filterFormattedDataById(formattedData, clickedItem)
|
214
|
-
const updatedTree = changeItem(filtered[0], check)
|
215
|
-
console.log(updatedTree);
|
250
|
+
const filtered = filterFormattedDataById(formattedData, clickedItem)
|
251
|
+
const updatedTree = changeItem(filtered[0], check)
|
216
252
|
if (returnAllSelected) {
|
217
|
-
onSelect(getCheckedItems(updatedTree))
|
253
|
+
onSelect(getCheckedItems(updatedTree))
|
218
254
|
} else {
|
219
|
-
onSelect(getDefaultCheckedItems(updatedTree))
|
255
|
+
onSelect(getDefaultCheckedItems(updatedTree))
|
220
256
|
}
|
221
|
-
}
|
257
|
+
}
|
222
258
|
|
223
|
-
const isExpanded = (item: any) => expanded.indexOf(item.id) > -1
|
259
|
+
const isExpanded = (item: any) => expanded.indexOf(item.id) > -1
|
224
260
|
|
225
261
|
//handle click on chevron toggles in dropdown
|
226
262
|
const handleToggleClick = (id: string, event: React.MouseEvent) => {
|
227
|
-
event.stopPropagation()
|
228
|
-
const clickedItem = filterFormattedDataById(formattedData, id)
|
263
|
+
event.stopPropagation()
|
264
|
+
const clickedItem = filterFormattedDataById(formattedData, id)
|
229
265
|
if (clickedItem) {
|
230
|
-
let expandedArray = [...expanded]
|
231
|
-
const itemExpanded = isExpanded(clickedItem[0])
|
266
|
+
let expandedArray = [...expanded]
|
267
|
+
const itemExpanded = isExpanded(clickedItem[0])
|
232
268
|
|
233
269
|
if (itemExpanded)
|
234
|
-
expandedArray = expandedArray.filter((i) => i != clickedItem[0].id)
|
235
|
-
else expandedArray.push(clickedItem[0].id)
|
270
|
+
expandedArray = expandedArray.filter((i) => i != clickedItem[0].id)
|
271
|
+
else expandedArray.push(clickedItem[0].id)
|
236
272
|
|
237
|
-
setExpanded(expandedArray)
|
273
|
+
setExpanded(expandedArray)
|
238
274
|
}
|
239
|
-
}
|
275
|
+
}
|
240
276
|
|
241
277
|
//rendering formattedData to UI based on typeahead
|
242
278
|
const renderNestedOptions = (items: { [key: string]: any }[]) => {
|
@@ -246,8 +282,8 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
246
282
|
items.map((item: { [key: string]: any }) => {
|
247
283
|
return (
|
248
284
|
<>
|
249
|
-
<li key={item.id} className=
|
250
|
-
<div className=
|
285
|
+
<li key={item.id} className='dropdown_item' data-name={item.id}>
|
286
|
+
<div className='dropdown_item_checkbox_row'>
|
251
287
|
<div
|
252
288
|
key={isExpanded(item) ? "chevron-down" : "chevron-right"}
|
253
289
|
>
|
@@ -263,17 +299,17 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
263
299
|
onClick={(event: any) =>
|
264
300
|
handleToggleClick(item.id, event)
|
265
301
|
}
|
266
|
-
variant=
|
302
|
+
variant='link'
|
267
303
|
/>
|
268
304
|
</div>
|
269
305
|
<Checkbox text={item.label} id={item.id}>
|
270
306
|
<input
|
271
307
|
checked={item.checked}
|
272
|
-
type=
|
308
|
+
type='checkbox'
|
273
309
|
name={item.label}
|
274
310
|
value={item.label}
|
275
311
|
onChange={(e) => {
|
276
|
-
handledropdownItemClick(e, !item.checked)
|
312
|
+
handledropdownItemClick(e, !item.checked)
|
277
313
|
}}
|
278
314
|
/>
|
279
315
|
</Checkbox>
|
@@ -286,23 +322,27 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
286
322
|
)}
|
287
323
|
</li>
|
288
324
|
</>
|
289
|
-
)
|
325
|
+
)
|
290
326
|
})}
|
291
327
|
</ul>
|
292
|
-
)
|
293
|
-
}
|
328
|
+
)
|
329
|
+
}
|
294
330
|
|
295
331
|
return (
|
296
332
|
<div {...ariaProps} {...dataProps} className={classes} id={id}>
|
297
|
-
<div ref={dropdownRef} className=
|
298
|
-
<div className=
|
299
|
-
<div className=
|
333
|
+
<div ref={dropdownRef} className='wrapper'>
|
334
|
+
<div className='input_wrapper' onClick={handleInputWrapperClick}>
|
335
|
+
<div className='input_inner_container'>
|
336
|
+
{returnedArray.map((item) => (
|
337
|
+
<input type='hidden' name={name} value={item.id} />
|
338
|
+
))}
|
339
|
+
|
300
340
|
{returnedArray.length !== 0 && returnAllSelected
|
301
341
|
? returnedArray.map((item, index) => (
|
302
342
|
<FormPill
|
303
343
|
key={index}
|
304
344
|
text={item.label}
|
305
|
-
size=
|
345
|
+
size='small'
|
306
346
|
onClick={(event: any) => handlePillClose(event, item)}
|
307
347
|
/>
|
308
348
|
))
|
@@ -313,29 +353,29 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
313
353
|
<FormPill
|
314
354
|
key={index}
|
315
355
|
text={item.label}
|
316
|
-
size=
|
356
|
+
size='small'
|
317
357
|
onClick={(event: any) => handlePillClose(event, item)}
|
318
358
|
/>
|
319
359
|
))}
|
320
360
|
{returnedArray.length !== 0 && returnAllSelected && <br />}
|
321
361
|
{defaultReturn.length !== 0 && !returnAllSelected && <br />}
|
322
362
|
<input
|
323
|
-
id=
|
363
|
+
id='multiselect_input'
|
324
364
|
onChange={(e) => {
|
325
|
-
setFilterItem(e.target.value)
|
365
|
+
setFilterItem(e.target.value)
|
326
366
|
}}
|
327
|
-
placeholder=
|
367
|
+
placeholder='Start typing...'
|
328
368
|
value={filterItem}
|
329
369
|
onClick={() => setIsClosed(false)}
|
330
370
|
/>
|
331
371
|
</div>
|
332
372
|
{isClosed ? (
|
333
|
-
<div key=
|
334
|
-
<Icon icon=
|
373
|
+
<div key='chevron-down'>
|
374
|
+
<Icon icon='chevron-down' />
|
335
375
|
</div>
|
336
376
|
) : (
|
337
|
-
<div key=
|
338
|
-
<Icon icon=
|
377
|
+
<div key='chevron-up'>
|
378
|
+
<Icon icon='chevron-up' />
|
339
379
|
</div>
|
340
380
|
)}
|
341
381
|
</div>
|
@@ -346,7 +386,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
346
386
|
</div>
|
347
387
|
</div>
|
348
388
|
</div>
|
349
|
-
)
|
350
|
-
}
|
389
|
+
)
|
390
|
+
}
|
351
391
|
|
352
|
-
export default MultiLevelSelect
|
392
|
+
export default MultiLevelSelect
|
@@ -8,6 +8,7 @@
|
|
8
8
|
label: "People",
|
9
9
|
value: "People",
|
10
10
|
id: "people1",
|
11
|
+
checked: true,
|
11
12
|
children: [
|
12
13
|
{
|
13
14
|
label: "Talent Acquisition",
|
@@ -18,6 +19,7 @@
|
|
18
19
|
label: "Business Affairs",
|
19
20
|
value: "Business Affairs",
|
20
21
|
id: "business1",
|
22
|
+
checked: true,
|
21
23
|
children: [
|
22
24
|
{
|
23
25
|
label: "Initiatives",
|
@@ -61,12 +63,18 @@
|
|
61
63
|
],
|
62
64
|
},
|
63
65
|
],
|
64
|
-
|
66
|
+
}] %>
|
65
67
|
|
66
68
|
|
67
|
-
<%= pb_rails("multi_level_select", props: {
|
68
|
-
id: "default-multi-level-select",
|
69
|
-
tree_data:treeData
|
70
|
-
}) %>
|
71
|
-
|
72
69
|
|
70
|
+
<%= pb_form_with(scope: :example, url: "", method: :get) do |form| %>
|
71
|
+
<%= pb_rails("multi_level_select", props: {
|
72
|
+
id: "default-multi-level-select-test",
|
73
|
+
name: "my_array[]",
|
74
|
+
tree_data: treeData
|
75
|
+
}) %>
|
76
|
+
<%= form.actions do |action| %>
|
77
|
+
<%= action.submit %>
|
78
|
+
<%= action.button props: { type: "reset", text: "Cancel", variant: "secondary" } %>
|
79
|
+
<% end %>
|
80
|
+
<% end %>
|
@@ -72,15 +72,19 @@ const MultiLevelSelectDefault = (props) => {
|
|
72
72
|
return (
|
73
73
|
<div>
|
74
74
|
<MultiLevelSelect
|
75
|
-
id=
|
75
|
+
id='multiselect-default'
|
76
76
|
onSelect={(selectedNodes) =>
|
77
|
-
console.log(
|
78
|
-
|
77
|
+
console.log(
|
78
|
+
"Selected Items (default... with ids only)",
|
79
|
+
selectedNodes
|
80
|
+
)
|
81
|
+
}
|
82
|
+
returnAllSelected
|
79
83
|
treeData={treeData}
|
80
84
|
{...props}
|
81
85
|
/>
|
82
86
|
</div>
|
83
|
-
)
|
87
|
+
)
|
84
88
|
};
|
85
89
|
|
86
90
|
export default MultiLevelSelectDefault;
|
@@ -2,4 +2,4 @@ The MultiLevelSelect kit renders a multi leveled select dropdown based on data f
|
|
2
2
|
|
3
3
|
For the React version of the kit, the `onSelect` prop returns an array of all checked items, irrespective of whether it is a parent, child or grandchild. Open the console on this example and check and uncheck checkboxes to see this is action!
|
4
4
|
|
5
|
-
|
5
|
+
By default, the return will be an array of Id's. If you want to return the entire object, you can pass `returnCompleteData` as true. This will return an array of objects.
|
@@ -3,7 +3,6 @@
|
|
3
3
|
value: "Power Home Remodeling",
|
4
4
|
id: "powerhome1",
|
5
5
|
expanded: true,
|
6
|
-
|
7
6
|
children: [
|
8
7
|
{
|
9
8
|
label: "People",
|
@@ -62,11 +61,19 @@
|
|
62
61
|
],
|
63
62
|
},
|
64
63
|
],
|
65
|
-
|
64
|
+
}] %>
|
65
|
+
|
66
66
|
|
67
67
|
|
68
|
-
<%=
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
<%= pb_form_with(scope: :example, url: "", method: :get) do |form| %>
|
69
|
+
<%= pb_rails("multi_level_select", props: {
|
70
|
+
id: "default-multi-level-select-test-return-all-selected",
|
71
|
+
name: "q[user_title_org_level_id_in]",
|
72
|
+
tree_data: treeData,
|
73
|
+
return_all_selected: true
|
74
|
+
}) %>
|
75
|
+
<%= form.actions do |action| %>
|
76
|
+
<%= action.submit %>
|
77
|
+
<%= action.button props: { type: "reset", text: "Cancel", variant: "secondary" } %>
|
78
|
+
<% end %>
|
79
|
+
<% end %>
|
data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.jsx
CHANGED
@@ -74,7 +74,7 @@ const MultiLevelSelectReturnAllSelected = (props) => {
|
|
74
74
|
<MultiLevelSelect
|
75
75
|
id="multiselect-parent-persistence"
|
76
76
|
onSelect={(selectedNodes) =>
|
77
|
-
console.log("Selected Items", selectedNodes)
|
77
|
+
console.log("Selected Items with Return All Selected Data", selectedNodes)
|
78
78
|
}
|
79
79
|
returnAllSelected
|
80
80
|
treeData={treeData}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
<% treeData = [{
|
2
|
+
label: "Power Home Remodeling",
|
3
|
+
value: "Power Home Remodeling",
|
4
|
+
id: "powerhome1",
|
5
|
+
expanded: true,
|
6
|
+
children: [
|
7
|
+
{
|
8
|
+
label: "People",
|
9
|
+
value: "People",
|
10
|
+
id: "people1",
|
11
|
+
children: [
|
12
|
+
{
|
13
|
+
label: "Talent Acquisition",
|
14
|
+
value: "Talent Acquisition",
|
15
|
+
id: "talent1",
|
16
|
+
},
|
17
|
+
{
|
18
|
+
label: "Business Affairs",
|
19
|
+
value: "Business Affairs",
|
20
|
+
id: "business1",
|
21
|
+
children: [
|
22
|
+
{
|
23
|
+
label: "Initiatives",
|
24
|
+
value: "Initiatives",
|
25
|
+
id: "initiative1",
|
26
|
+
},
|
27
|
+
{
|
28
|
+
label: "Learning & Development",
|
29
|
+
value: "Learning & Development",
|
30
|
+
id: "development1",
|
31
|
+
},
|
32
|
+
],
|
33
|
+
},
|
34
|
+
{
|
35
|
+
label: "People Experience",
|
36
|
+
value: "People Experience",
|
37
|
+
id: "experience1",
|
38
|
+
},
|
39
|
+
],
|
40
|
+
},
|
41
|
+
{
|
42
|
+
label: "Contact Center",
|
43
|
+
value: "Contact Center",
|
44
|
+
id: "contact1",
|
45
|
+
children: [
|
46
|
+
{
|
47
|
+
label: "Appointment Management",
|
48
|
+
value: "Appointment Management",
|
49
|
+
id: "appointment1",
|
50
|
+
},
|
51
|
+
{
|
52
|
+
label: "Customer Service",
|
53
|
+
value: "Customer Service",
|
54
|
+
id: "customer1",
|
55
|
+
},
|
56
|
+
{
|
57
|
+
label: "Energy",
|
58
|
+
value: "Energy",
|
59
|
+
id: "energy1",
|
60
|
+
},
|
61
|
+
],
|
62
|
+
},
|
63
|
+
],
|
64
|
+
}] %>
|
65
|
+
|
66
|
+
|
67
|
+
<%= pb_rails("multi_level_select", props: {
|
68
|
+
id: "default-multi-level-select",
|
69
|
+
tree_data: treeData,
|
70
|
+
return_complete_data: true
|
71
|
+
}) %>
|
72
|
+
|
73
|
+
|