Skip to content

Commit 9174b89

Browse files
committed
feat(MultiSelect): add disabled options support; improve syntax
1 parent 2081cf4 commit 9174b89

File tree

1 file changed

+49
-28
lines changed

1 file changed

+49
-28
lines changed

js/src/multi-select.js

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import BaseComponent from './base-component'
2121
* ------------------------------------------------------------------------
2222
*/
2323

24-
const NAME = 'mutli-select'
25-
const DATA_KEY = 'coreui.mutli-select'
24+
const NAME = 'multi-select'
25+
const DATA_KEY = 'coreui.multi-select'
2626
const EVENT_KEY = `.${DATA_KEY}`
2727
const DATA_API_KEY = '.data-api'
2828

@@ -51,6 +51,7 @@ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
5151
const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`
5252
const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`
5353

54+
const CLASS_NAME_DISABLED = 'disabled'
5455
const CLASS_NAME_SELECT = 'form-multi-select'
5556
const CLASS_NAME_SELECT_DROPDOWN = 'form-multi-select-dropdown'
5657
const CLASS_NAME_SELECT_MULTIPLE = 'form-multi-select-multiple'
@@ -76,6 +77,7 @@ const CLASS_NAME_LABEL = 'label'
7677
const Default = {
7778
cleaner: true,
7879
multiple: true,
80+
name: '',
7981
placeholder: 'Select...',
8082
options: false,
8183
optionsMaxHeight: 'auto',
@@ -84,13 +86,14 @@ const Default = {
8486
searchNoResultsLabel: 'No results found',
8587
selectAll: true,
8688
selectAllLabel: 'Select all options',
87-
selectionType: 'tag',
89+
selectionType: 'tags',
8890
selectionTypeCounterText: 'item(s) selected'
8991
}
9092

9193
const DefaultType = {
9294
cleaner: 'boolean',
9395
multiple: 'boolean',
96+
name: 'string',
9497
placeholder: 'string',
9598
options: '(boolean|array)',
9699
optionsMaxHeight: '(number|string)',
@@ -189,6 +192,10 @@ class MultiSelect extends BaseComponent {
189192

190193
selectAll(options = this._options) {
191194
options.forEach(option => {
195+
if (option.disabled) {
196+
return
197+
}
198+
192199
if (option.label) {
193200
this.selectAll(option.options)
194201
return
@@ -198,8 +205,12 @@ class MultiSelect extends BaseComponent {
198205
})
199206
}
200207

201-
deselectAll(selection = this._selection) {
202-
selection.forEach(option => {
208+
deselectAll(options = this._options) {
209+
options.forEach(option => {
210+
if (option.disabled) {
211+
return
212+
}
213+
203214
if (option.label) {
204215
this.deselectAll(option.options)
205216
return
@@ -263,7 +274,6 @@ class MultiSelect extends BaseComponent {
263274
_getConfig(config) {
264275
config = {
265276
...Default,
266-
...Manipulator.getDataAttributes(this._element),
267277
...config
268278
}
269279
typeCheckConfig(NAME, config, DefaultType)
@@ -288,7 +298,8 @@ class MultiSelect extends BaseComponent {
288298
options.push({
289299
value: node.value,
290300
text: node.innerHTML,
291-
selected: node.selected
301+
selected: node.selected,
302+
disabled: node.disabled
292303
})
293304
}
294305

@@ -329,20 +340,13 @@ class MultiSelect extends BaseComponent {
329340
}
330341

331342
_createNativeSelect(data) {
332-
const select = document.createElement('select')
333-
select.classList.add(CLASS_NAME_SELECT)
334-
if (this._element.id) {
335-
select.id = this._element.id
336-
}
343+
this._element.classList.add(CLASS_NAME_SELECT)
337344

338345
if (this._config.multiple) {
339-
select.multiple = true
346+
this._element.setAttribute('multiple', true)
340347
}
341348

342-
this._createNativeOptions(select, data)
343-
344-
this._element.replaceWith(select)
345-
this._element = select
349+
this._createNativeOptions(this._element, data)
346350
}
347351

348352
_createNativeOptions(parentElement, options) {
@@ -356,6 +360,11 @@ class MultiSelect extends BaseComponent {
356360
} else {
357361
const opt = document.createElement('OPTION')
358362
opt.value = option.value
363+
364+
if (option.disabled === true) {
365+
opt.setAttribute('disabled', 'disabled')
366+
}
367+
359368
if (option.selected === true) {
360369
opt.setAttribute('selected', 'selected')
361370
}
@@ -383,7 +392,7 @@ class MultiSelect extends BaseComponent {
383392
div.classList.add(CLASS_NAME_SELECT_MULTIPLE)
384393
}
385394

386-
if (this._config.selectionType === 'tags') {
395+
if (this._config.multiple && this._config.selectionType === 'tags') {
387396
div.classList.add(CLASS_NAME_SELECTION_TAGS)
388397
}
389398

@@ -468,6 +477,11 @@ class MultiSelect extends BaseComponent {
468477
if (typeof option.value !== 'undefined') {
469478
const optionDiv = document.createElement('div')
470479
optionDiv.classList.add(CLASS_NAME_OPTION)
480+
481+
if (option.disabled) {
482+
optionDiv.classList.add(CLASS_NAME_DISABLED)
483+
}
484+
471485
if (this._config.optionsStyle === 'checkbox') {
472486
optionDiv.classList.add(CLASS_NAME_OPTION_WITH_CHECKBOX)
473487
}
@@ -512,8 +526,8 @@ class MultiSelect extends BaseComponent {
512526

513527
tag.remove()
514528
this._deselectOption(value)
515-
this._updateOptionsList()
516-
this._updateSearch()
529+
// this._updateOptionsList()
530+
// this._updateSearch()
517531
})
518532

519533
return tag
@@ -548,7 +562,11 @@ class MultiSelect extends BaseComponent {
548562
})
549563
}
550564

551-
SelectorEngine.findOne(`option[value="${value}"]`, this._element).selected = true
565+
const nativeOption = SelectorEngine.findOne(`option[value="${value}"]`, this._element)
566+
567+
if (nativeOption) {
568+
nativeOption.selected = true
569+
}
552570

553571
const option = SelectorEngine.findOne(`[data-value="${value}"]`, this._optionsElement)
554572
if (option) {
@@ -668,6 +686,10 @@ class MultiSelect extends BaseComponent {
668686
}
669687

670688
_updateSearchSize(size = 2) {
689+
if (!this._searchElement || !this._config.multiple) {
690+
return
691+
}
692+
671693
if (this._selection.length > 0 && (this._config.selectionType === 'tags' || this._config.selectionType === 'text')) {
672694
this._searchElement.size = size
673695
return
@@ -686,16 +708,15 @@ class MultiSelect extends BaseComponent {
686708
}
687709
}
688710

689-
_updateOptionsList() {
690-
const options = SelectorEngine.find(SELECTOR_OPTION, this._clone)
691-
711+
_updateOptionsList(options = this._options) {
692712
options.forEach(option => {
693-
if (this._selection.filter(e => e.value === option.dataset.value).length !== 0) {
694-
option.classList.add(CLASS_NAME_SELECTED)
713+
if (option.label) {
714+
this._updateOptionsList(option.options)
715+
return
695716
}
696717

697-
if (this._selection.filter(e => e.value === option.dataset.value).length === 0) {
698-
option.classList.remove(CLASS_NAME_SELECTED)
718+
if (option.selected) {
719+
this._selectOption(option.value, option.text)
699720
}
700721
})
701722
}

0 commit comments

Comments
 (0)