Intention and Description:Helps user select multiple options with a search capability.
Features:
- Single component can be called from anywhere.
- Set the Multi Select Label Name. @api labelName = '';
- Pass the Full option lists. @api allList = [];
- Pass placeholder name in search text box. @api placeHolder = 'Search...';
- Receive the selected items in Parent through onselected Event
Video:
Code Snippet:
simpleMultiSelect.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| <template>
<div class="slds-form-element" >
<label class="slds-form-element__label" for="combobox-unique-id">{labelName}</label>
<div class="slds-form-element__control">
<div class="slds-combobox_container slds-size_small">
<div class={comboClass} aria-expanded={listOpened}
aria-haspopup="listbox" role="combobox">
<div class="slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right">
<lightning-input id="input" value={searchInput} onclick={SearchClick} onchange={ChangeSearchInput}
variant="label-hidden" aria-autocomplete="list" role="textbox" autocomplete="off"
placeholder={placeHolder} type="text">
</lightning-input>
<span class="slds-icon_container slds-icon-utility-down slds-input__icon slds-input__icon_right"
>
<lightning-icon icon-name="utility:down" size="x-small" ></lightning-icon>
<span class="slds-assistive-text">Click to open the List</span>
</span>
</div>
<div class=" slds-form-element__control slds-input-has-icon slds-input-has-icon slds-input-has-icon_left-right" role="none">
<template for:each={selectedList} for:item="selectedItem">
<span key={selectedItem.value}>
<lightning-pill label={selectedItem.label} name={selectedItem.value} data-item={selectedItem.value}
onremove={handleRemoveRecord}>
</lightning-pill>
</span>
</template>
</div>
<div id="listbox-id-1"
class="zindexHigh slds-dropdown slds-dropdown_length-5 slds-dropdown_fluid"
role="listbox">
<div class="slds-size_2-of-2 slds-popover__body slds-popover__body_small">
<template for:each={displayList} for:item="Item">
<span key={Item.value}>
<lightning-input type="checkbox" label={Item.label} value={Item.value} checked={Item.selected} onchange={handleCheckboxChange}></lightning-input>
</span>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
|
simpleMultiSelect.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
| /* eslint-disable eqeqeq */
/* eslint-disable array-callback-return */
/* eslint-disable no-console */
/* eslint-disable no-alert */
import {
LightningElement,
api,
track
} from "lwc";
export default class SimpleMultiSelect extends LightningElement {
@api allList = []; //receive the full list from calling component
@api placeHolder = 'Search...'; // Display place holder Text in the input box
@api labelName = ''; //Label the Component
//contains list to be displayed
@track displayList = [];
//contains the selected list
@api selectedList = [];
//search letters input by the user
@track searchInput = '';
//toggle between the list opened and Closed, default is false
@track listOpened = false;
//style of the div
@track comboClass = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click';
//initialization of the list
connectedCallback()
{
this.allList.map(allListElement => {
if (allListElement.selected) {
this.selectedList = [
...this.selectedList,
{
label: allListElement.label,
value: allListElement.value,
selected: allListElement.selected
}
]
}
});
}
//fires when the list expands or collapsed
SearchClick() {
if (!this.listOpened) {
this.listOpened = true;
this.comboClass = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-is-open';
this.displayList = []; //initialize the array before assigning values coming from apex
this.allList.map(allListElement => {
if (allListElement.selected) {
//Add item to selectedList of not already present
if (this.selectedList.find(element => element.value == allListElement.value) == null) {
this.selectedList = [
...this.selectedList,
{
label: allListElement.label,
value: allListElement.value,
selected: allListElement.selected
}
]
}
}
//Add item to displayList of not already present
this.displayList = [
...this.displayList,
{
label: allListElement.label,
value: allListElement.value,
selected: (this.selectedList.find(element => element.value == allListElement.value) != null)
}
];
});
}
else if (this.listOpened)
{
this.searchInput = ''; //clearing the text
this.listOpened = false;
this.comboClass = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click';
//Pulishing Selected items through Event After closeing the dropdown list
this.publishEvent();
}
}
//filter the display options based on user's search input
ChangeSearchInput(event) {
this.listOpened = true;
this.comboClass = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click slds-is-open';
this.searchInput = event.target.value.toLowerCase();
this.displayList = []; //initialize the array before assigning values coming from apex
//filter the global list and repolulating the display options
let filterList = this.allList.filter(
item => item.value.toLowerCase().includes(this.searchInput.trim()) == true
);
filterList.map(allListElement => {
this.displayList = [
...this.displayList,
{
label: allListElement.label,
value: allListElement.value,
selected: this.selectedList.find(element => element.value == allListElement.value) != null
}
];
});
}
//handle check box changes to re-evaluate the display option and selected list
handleCheckboxChange(e) {
if (e.detail.checked) {
if (this.selectedList.find(element => element.value == e.target.value) == null) {
this.selectedList = [
...this.selectedList,
{
label: e.target.label,
value: e.target.value,
selected: e.detail.checked
}
]
}
} else // unchecked
{
this.selectedList = this.selectedList.filter(
item => item.value != e.target.value
);
}
this.displayList.map(element => {
if (element.value == e.target.value) {
element.selected = e.detail.checked;
}
});
}
//handle pill action. re-evaluate display option and selected list
handleRemoveRecord(e) {
const removeItem = e.target.dataset.item;
this.selectedList = this.selectedList.filter(item => item.value != removeItem);
this.displayList.map(element => {
if (element.value == removeItem) {
element.selected = false;
}
});
}
//Publishning the selected list
publishEvent()
{
// Creates the event with selected items.
const selectedEvent = new CustomEvent('selected', { detail: this.selectedList });
// Dispatches the event.
this.dispatchEvent(selectedEvent);
}
}
|
simpleMultiSelect.css
1
2
3
4
5
6
7
8
9
10
| .zindexHigh {
z-index: 999;
top: 30px;
position: absolute;
}
.zindex2 {
z-index: 2;
position: relative;
}
|
testMultiSelect ( Parent Calling Component)
testMultiSelect.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| <template>
This is custom MultiSelect Test
</br>
<c-simple-multi-select all-list={simpleMultiSelectList} place-holder="Select..."
label-name="My MultiSelect" onselected={Displayitems}>
</c-simple-multi-select>
</br>
<lightning-card title="Select Items in Parent" icon-name="custom:custom67">
<div class="slds-m-horizontal_medium">
<template for:each={objectInfo} for:item='item'>
<li class="slds-listbox__item slds-search-dropdown-list-items" key={item.label}>
<div>{item.value}</div>
</li>
</template>
</div>
</lightning-card>
</template>
|
testMultiSelect.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| /* eslint-disable no-console */
import { LightningElement,track } from 'lwc';
export default class TestMultiSelect extends LightningElement {
@track simpleMultiSelectList = [];
@track objectInfo = [];
connectedCallback()
{
this.simpleMultiSelectList.push({label: 'Jiten',value: 'Jiten', selected : false});
this.simpleMultiSelectList.push({label: 'Animesh',value: 'Animesh', selected : false});
this.simpleMultiSelectList.push({label: 'Santanu Boral',value: 'Santanu Boral', selected : true});
this.simpleMultiSelectList.push({label: 'Santanu Pal',value: 'Santanu Pal', selected : false});
this.simpleMultiSelectList.push({label: 'Suman',value: 'Suman', selected : false});
this.simpleMultiSelectList.push({label: 'Option 6',value: 'Option 6', selected : false});
this.simpleMultiSelectList.push({label: 'Option 8',value: 'Option 8', selected : false});
this.simpleMultiSelectList.push({label: 'Option 9',value: 'Option 9', selected : false});
this.simpleMultiSelectList.push({label: 'Option 10',value: 'Option 10', selected : false});
this.simpleMultiSelectList.push({label: 'Option 11',value: 'Option 11', selected : false});
this.simpleMultiSelectList.push({label: 'Option 12',value: 'Option 12', selected : false});
}
Displayitems(event)
{
console.log(event.detail);
this.objectInfo = event.detail;
}
}
|