@@ -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