Skip to content

Commit 7fb3807

Browse files
authored
Bug fix for #41 - Preventing blur on IE (#48)
* Bug fix for blur on IE * Fixed 'no results' displayed after selection
1 parent 57eec4e commit 7fb3807

File tree

2 files changed

+46
-41
lines changed

2 files changed

+46
-41
lines changed

src/main/default/lwc/lookup/lookup.html

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,12 @@
6565
<!-- Search input end -->
6666

6767
<!-- Result list box start -->
68-
<div id="listbox" role="listbox" onclick={handleComboboxClick}>
68+
<div
69+
id="listbox"
70+
role="listbox"
71+
onmousedown={handleComboboxMouseDown}
72+
onmouseup={handleComboboxMouseUp}
73+
>
6974
<ul class={getListboxClass} role="presentation">
7075
<!-- Spinner to display when waiting for results of search -->
7176
<div if:true={loading}>
@@ -134,7 +139,7 @@
134139
role="group"
135140
aria-label="Selected Options:"
136141
>
137-
<template for:each={curSelection} for:item="item">
142+
<template for:each={selection} for:item="item">
138143
<li key={item.id} role="presentation" class="slds-listbox__item">
139144
<lightning-pill
140145
label={item.title}

src/main/default/lwc/lookup/lookup.js

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ export default class Lookup extends LightningElement {
1818
loading = false;
1919
isDirty = false;
2020

21-
cleanSearchTerm;
22-
blurTimeout;
23-
searchThrottlingTimeout;
24-
curSelection = [];
21+
_cleanSearchTerm;
22+
_cancelBlur = false;
23+
_searchThrottlingTimeout;
24+
_curSelection = [];
2525

2626
// EXPOSED FUNCTIONS
2727
@api
2828
set selection(initialSelection) {
29-
this.curSelection = Array.isArray(initialSelection) ? initialSelection : [initialSelection];
29+
this._curSelection = Array.isArray(initialSelection) ? initialSelection : [initialSelection];
3030
this.isDirty = false;
3131
}
3232
get selection() {
33-
return this.curSelection;
33+
return this._curSelection;
3434
}
3535

3636
@api
@@ -67,7 +67,7 @@ export default class Lookup extends LightningElement {
6767

6868
@api
6969
getSelection() {
70-
return this.curSelection;
70+
return this._curSelection;
7171
}
7272

7373
@api
@@ -82,12 +82,12 @@ export default class Lookup extends LightningElement {
8282

8383
// Compare clean new search term with current one and abort if identical
8484
const newCleanSearchTerm = newSearchTerm.trim().replace(/\*/g, '').toLowerCase();
85-
if (this.cleanSearchTerm === newCleanSearchTerm) {
85+
if (this._cleanSearchTerm === newCleanSearchTerm) {
8686
return;
8787
}
8888

8989
// Save clean search term
90-
this.cleanSearchTerm = newCleanSearchTerm;
90+
this._cleanSearchTerm = newCleanSearchTerm;
9191

9292
// Ignore search terms that are too small
9393
if (newCleanSearchTerm.length < MINIMAL_SEARCH_TERM_LENGTH) {
@@ -96,25 +96,25 @@ export default class Lookup extends LightningElement {
9696
}
9797

9898
// Apply search throttling (prevents search if user is still typing)
99-
if (this.searchThrottlingTimeout) {
100-
clearTimeout(this.searchThrottlingTimeout);
99+
if (this._searchThrottlingTimeout) {
100+
clearTimeout(this._searchThrottlingTimeout);
101101
}
102102
// eslint-disable-next-line @lwc/lwc/no-async-operation
103-
this.searchThrottlingTimeout = setTimeout(() => {
103+
this._searchThrottlingTimeout = setTimeout(() => {
104104
// Send search event if search term is long enougth
105-
if (this.cleanSearchTerm.length >= MINIMAL_SEARCH_TERM_LENGTH) {
105+
if (this._cleanSearchTerm.length >= MINIMAL_SEARCH_TERM_LENGTH) {
106106
// Display spinner until results are returned
107107
this.loading = true;
108108

109109
const searchEvent = new CustomEvent('search', {
110110
detail: {
111-
searchTerm: this.cleanSearchTerm,
112-
selectedIds: this.curSelection.map((element) => element.id)
111+
searchTerm: this._cleanSearchTerm,
112+
selectedIds: this._curSelection.map((element) => element.id)
113113
}
114114
});
115115
this.dispatchEvent(searchEvent);
116116
}
117-
this.searchThrottlingTimeout = null;
117+
this._searchThrottlingTimeout = null;
118118
}, SEARCH_DELAY);
119119
}
120120

@@ -130,7 +130,7 @@ export default class Lookup extends LightningElement {
130130
}
131131

132132
hasSelection() {
133-
return this.curSelection.length > 0;
133+
return this._curSelection.length > 0;
134134
}
135135

136136
// EVENT HANDLING
@@ -152,25 +152,31 @@ export default class Lookup extends LightningElement {
152152
return;
153153
}
154154
selectedItem = selectedItem[0];
155-
const newSelection = [...this.curSelection];
155+
const newSelection = [...this._curSelection];
156156
newSelection.push(selectedItem);
157-
this.curSelection = newSelection;
157+
this._curSelection = newSelection;
158158
this.isDirty = true;
159159

160160
// Reset search
161+
this._cleanSearchTerm = '';
161162
this.searchTerm = '';
162163
this.searchResults = [];
163164

164165
// Notify parent components that selection has changed
165166
this.dispatchEvent(new CustomEvent('selectionchange'));
166167
}
167168

168-
handleComboboxClick() {
169-
// Hide combobox immediatly
170-
if (this.blurTimeout) {
171-
window.clearTimeout(this.blurTimeout);
169+
handleComboboxMouseDown(event) {
170+
const mainButton = 0;
171+
if (event.button === mainButton) {
172+
this._cancelBlur = true;
172173
}
173-
this.hasFocus = false;
174+
}
175+
176+
handleComboboxMouseUp() {
177+
this._cancelBlur = false;
178+
// Re-focus to text input for the next blur event
179+
this.template.querySelector('input').focus();
174180
}
175181

176182
handleFocus() {
@@ -182,28 +188,23 @@ export default class Lookup extends LightningElement {
182188
}
183189

184190
handleBlur() {
185-
// Prevent action if selection is not allowed
186-
if (!this.isSelectionAllowed()) {
191+
// Prevent action if selection is either not allowed or cancelled
192+
if (!this.isSelectionAllowed() || this._cancelBlur) {
187193
return;
188194
}
189-
// Delay hiding combobox so that we can capture selected result
190-
// eslint-disable-next-line @lwc/lwc/no-async-operation
191-
this.blurTimeout = window.setTimeout(() => {
192-
this.hasFocus = false;
193-
this.blurTimeout = null;
194-
}, 300);
195+
this.hasFocus = false;
195196
}
196197

197198
handleRemoveSelectedItem(event) {
198199
const recordId = event.currentTarget.name;
199-
this.curSelection = this.curSelection.filter((item) => item.id !== recordId);
200+
this._curSelection = this._curSelection.filter((item) => item.id !== recordId);
200201
this.isDirty = true;
201202
// Notify parent components that selection has changed
202203
this.dispatchEvent(new CustomEvent('selectionchange'));
203204
}
204205

205206
handleClearSelection() {
206-
this.curSelection = [];
207+
this._curSelection = [];
207208
this.isDirty = true;
208209
// Notify parent components that selection has changed
209210
this.dispatchEvent(new CustomEvent('selectionchange'));
@@ -224,7 +225,7 @@ export default class Lookup extends LightningElement {
224225

225226
get getDropdownClass() {
226227
let css = 'slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click ';
227-
if (this.hasFocus && this.cleanSearchTerm && this.cleanSearchTerm.length >= MINIMAL_SEARCH_TERM_LENGTH) {
228+
if (this.hasFocus && this._cleanSearchTerm && this._cleanSearchTerm.length >= MINIMAL_SEARCH_TERM_LENGTH) {
228229
css += 'slds-is-open';
229230
}
230231
return css;
@@ -267,7 +268,7 @@ export default class Lookup extends LightningElement {
267268
}
268269

269270
get getSelectIconName() {
270-
return this.hasSelection() ? this.curSelection[0].icon : 'standard:default';
271+
return this.hasSelection() ? this._curSelection[0].icon : 'standard:default';
271272
}
272273

273274
get getSelectIconClass() {
@@ -278,15 +279,14 @@ export default class Lookup extends LightningElement {
278279
if (this.isMultiEntry) {
279280
return this.searchTerm;
280281
}
281-
return this.hasSelection() ? this.curSelection[0].title : this.searchTerm;
282+
return this.hasSelection() ? this._curSelection[0].title : this.searchTerm;
282283
}
283284

284285
get getInputTitle() {
285286
if (this.isMultiEntry) {
286287
return '';
287288
}
288-
289-
return this.hasSelection() ? this.curSelection[0].title : '';
289+
return this.hasSelection() ? this._curSelection[0].title : '';
290290
}
291291

292292
get getListboxClass() {

0 commit comments

Comments
 (0)