diff --git a/README.md b/README.md
index 81262d4..ea1b0d7 100644
--- a/README.md
+++ b/README.md
@@ -240,9 +240,12 @@ Join our [Discord channel](https://discord.gg/WhX2nG6GTQ) or [open an issue](htt
| **filterResults** | `boolean` | `true` | Whether option list should be filtered by search query. This may be set to `false` if you are handling filtering manually when returning async options. |
| **minChars** | `number` | `0` | The minimum number of characters that should be typed to refresh async option list. If `0` it will refresh even when the search field becomes empty. |
| **resolveOnLoad** | `boolean` | `true` | Whether async options should be loaded initially (with an empty query). This should be `true` if you are planning to load non-object value(s) initially while using async options (to fetch matching objects for values). |
-| **appendNewTag** | `boolean` | `true` | Whether it should append new tag automatically to option list when using `tags` mode with `createTag`. If set to `false` you need to take care of appending a new tag to the provided `:options` list upon `@tag` event. |
-| **createTag** | `boolean` | `false` | Whether it should allow creating new tag based on search query when using `tags` mode. |
-| **addTagOn** | `array` | `['enter']` | The list of keys that creates a new tag while typing in the search field when having `createTag` enabled. Possible values: `'enter'\|'space'\|'tab'\|';'\|','`. |
+| **appendNewTag** | `boolean` | `true` | **Deprecated 2.3.0: use `appendNewOption` instead.**
Whether it should append new tag automatically to option list when using `tags` mode with `createTag`. If set to `false` you need to take care of appending a new tag to the provided `:options` list upon `@tag` event. |
+| **createTag** | `boolean` | `false` | **Deprecated 2.3.0: use `createOption` instead.**
Whether it should allow creating new tags based on search query when using `tags` mode. |
+| **addTagOn** | `array` | `['enter']` | **Deprecated 2.3.0: use `addOptionOn` instead.**
The list of keys that creates a new tag while typing in the search field when having `createTag` enabled. Possible values: `'enter'\|'space'\|'tab'\|';'\|','`. |
+| **appendNewOption** | `boolean` | `true` | Whether it should append new option automatically to option list when `searchable` and `createTag` are enabled. If set to `false` you need to take care of appending a new option to the provided `:options` list upon `@option` event. |
+| **createOption** | `boolean` | `false` | Whether it should allow creating new options based on search query when `searchable` is enabled. |
+| **addOptionOn** | `array` | `['enter']` | The list of keys that creates a new option while typing in the search field when having `createOption` enabled. Possible values: `'enter'\|'space'\|'tab'\|';'\|','`. |
| **hideSelected** | `boolean` | `true` | Whether selected options should be excluded from the option list when using `multiple` or `tags` mode. |
| **showOptions** | `boolean` | `true` | Whether option list should be displayed. Can be used to create free-typed tags. |
| **object** | `boolean` | `false` | Whether the value should be stored as an object.
If **false**:
`value: ['js','jsx','ts']`
If **true**:
`value: [`
`{value:'js',label:'Javascript'},`
`{value:'jsx',label:'JSX'},`
`{value:'ts',label:'Typescript'}`
`]` |
@@ -290,7 +293,8 @@ mounted() {
| **@open** | | Emitted after opening the option list. |
| **@search-change** | `query` | Emitted after a character is typed. |
| **@select** | `option` | Emitted after an option or tag is selected. |
-| **@tag** | `query` | Emitted after enter is hit when a new tag is being created. |
+| **@tag** | `query` | **Deprecated 2.3.0: use `@option` instead**. Emitted after enter is hit when a new tag is being created. |
+| **@option** | `query` | Emitted after enter is hit when a new option is being created. |
| **@clear** | | Emitted when the options are cleared. |
| **@paste** | `Event` | Emitted when value is pasted into the search field. |
diff --git a/src/Multiselect.d.ts b/src/Multiselect.d.ts
index 894b8c5..54dc55a 100644
--- a/src/Multiselect.d.ts
+++ b/src/Multiselect.d.ts
@@ -29,8 +29,11 @@ declare class Multiselect extends Vue {
minChars?: number;
resolveOnLoad?: boolean;
appendNewTag?: boolean;
+ appendNewOption?: boolean;
createTag?: boolean;
+ createOption?: boolean;
addTagOn?: string[];
+ addOptionOn?: string[];
hideSelected?: boolean;
showOptions?: boolean;
object?: boolean;
@@ -54,6 +57,7 @@ declare class Multiselect extends Vue {
$emit(eventName: 'remove', e: {originalEvent: Event, value: any, option: any}): this;
$emit(eventName: 'search-change', e: {originalEvent: Event, query: string}): this;
$emit(eventName: 'tag', e: {originalEvent: Event, query: string}): this;
+ $emit(eventName: 'option', e: {originalEvent: Event, query: string}): this;
$emit(eventName: 'paste', e: {originalEvent: Event}): this;
$emit(eventName: 'open'): this;
$emit(eventName: 'close'): this;
diff --git a/src/Multiselect.vue b/src/Multiselect.vue
index 1b01f73..da1298a 100644
--- a/src/Multiselect.vue
+++ b/src/Multiselect.vue
@@ -209,7 +209,7 @@
name: 'Multiselect',
emits: [
'open', 'close', 'select', 'deselect',
- 'input', 'search-change', 'tag', 'update:modelValue',
+ 'input', 'search-change', 'tag', 'option', 'update:modelValue',
'change', 'clear'
],
props: {
@@ -281,12 +281,32 @@
createTag: {
type: Boolean,
required: false,
- default: false,
+ default: undefined,
+ },
+ createOption: {
+ type: Boolean,
+ required: false,
+ default: undefined,
},
appendNewTag: {
type: Boolean,
required: false,
- default: true,
+ default: undefined,
+ },
+ appendNewOption: {
+ type: Boolean,
+ required: false,
+ default: undefined,
+ },
+ addTagOn: {
+ type: Array,
+ required: false,
+ default: undefined,
+ },
+ addOptionOn: {
+ type: Array,
+ required: false,
+ default: undefined,
},
caret: {
type: Boolean,
@@ -367,11 +387,6 @@
required: false,
default: true,
},
- addTagOn: {
- type: Array,
- required: false,
- default: () => (['enter']),
- },
required: {
type: Boolean,
required: false,
diff --git a/src/composables/useKeyboard.js b/src/composables/useKeyboard.js
index 58a2208..34cf1c9 100644
--- a/src/composables/useKeyboard.js
+++ b/src/composables/useKeyboard.js
@@ -1,10 +1,11 @@
-import { toRefs } from 'composition-api'
+import { toRefs, computed } from 'composition-api'
export default function useKeyboard (props, context, dep)
{
const {
- mode, addTagOn, createTag, openDirection, searchable,
+ mode, addTagOn, openDirection, searchable,
showOptions, valueProp, groups: groupped,
+ addOptionOn: addOptionOn_, createTag, createOption: createOption_,
} = toRefs(props)
// ============ DEPENDENCIES ============
@@ -19,6 +20,25 @@ export default function useKeyboard (props, context, dep)
const blur = dep.blur
const fo = dep.fo
+ // ============== COMPUTED ==============
+
+ // no export
+ const createOption = computed(() => {
+ return createTag.value || createOption_.value || false
+ })
+
+ // no export
+ const addOptionOn = computed(() => {
+ if (addTagOn.value !== undefined) {
+ return addTagOn.value
+ }
+ else if (addOptionOn_.value !== undefined) {
+ return addOptionOn_.value
+ }
+
+ return ['enter']
+ })
+
// =============== METHODS ==============
// no export
@@ -28,7 +48,7 @@ export default function useKeyboard (props, context, dep)
// In such case we need to set the pointer manually to the
// first option, which equals to the option created from
// the search value.
- if (mode.value === 'tags' && !showOptions.value && createTag.value && searchable.value && !groupped.value) {
+ if (mode.value === 'tags' && !showOptions.value && createOption.value && searchable.value && !groupped.value) {
setPointer(fo.value[fo.value.map(o => o[valueProp.value]).indexOf(search.value)])
}
}
@@ -54,7 +74,7 @@ export default function useKeyboard (props, context, dep)
case 'Enter':
e.preventDefault()
- if (mode.value === 'tags' && addTagOn.value.indexOf('enter') === -1 && createTag.value) {
+ if (addOptionOn.value.indexOf('enter') === -1 && createOption.value) {
return
}
@@ -63,11 +83,19 @@ export default function useKeyboard (props, context, dep)
break
case ' ':
- if (searchable.value && mode.value !== 'tags' && !createTag.value) {
+ if (!createOption.value && !searchable.value) {
+ e.preventDefault()
+
+ preparePointer()
+ selectPointer()
return
}
- if (mode.value === 'tags' && ((addTagOn.value.indexOf('space') === -1 && createTag.value) || !createTag.value)) {
+ if (!createOption.value) {
+ return false
+ }
+
+ if (addOptionOn.value.indexOf('space') === -1 && createOption.value) {
return
}
@@ -80,11 +108,7 @@ export default function useKeyboard (props, context, dep)
case 'Tab':
case ';':
case ',':
- if (mode.value !== 'tags') {
- return
- }
-
- if (addTagOn.value.indexOf(e.key.toLowerCase()) === -1 || !createTag.value) {
+ if (addOptionOn.value.indexOf(e.key.toLowerCase()) === -1 || !createOption.value) {
return
}
diff --git a/src/composables/useOptions.js b/src/composables/useOptions.js
index 18c009f..5278f31 100644
--- a/src/composables/useOptions.js
+++ b/src/composables/useOptions.js
@@ -7,11 +7,11 @@ import arraysEqual from './../utils/arraysEqual'
export default function useOptions (props, context, dep)
{
const {
- options, mode, trackBy: trackBy_, limit, hideSelected, createTag, label,
- appendNewTag, multipleLabel, object, loading, delay, resolveOnLoad,
+ options, mode, trackBy: trackBy_, limit, hideSelected, createTag, createOption: createOption_, label,
+ appendNewTag, appendNewOption: appendNewOption_, multipleLabel, object, loading, delay, resolveOnLoad,
minChars, filterResults, clearOnSearch, clearOnSelect, valueProp,
canDeselect, max, strict, closeOnSelect, groups: groupped, groupLabel,
- groupOptions, groupHideEmpty, groupSelect,
+ groupOptions, groupHideEmpty, groupSelect,
} = toRefs(props)
// ============ DEPENDENCIES ============
@@ -41,6 +41,22 @@ export default function useOptions (props, context, dep)
// ============== COMPUTED ==============
+ // no export
+ const createOption = computed(() => {
+ return createTag.value || createOption_.value || false
+ })
+
+ // no export
+ const appendNewOption = computed(() => {
+ if (appendNewTag.value !== undefined) {
+ return appendNewTag.value
+ } else if (appendNewOption_.value !== undefined) {
+ return appendNewOption_.value
+ }
+
+ return true
+ })
+
// no export
// extendedOptions
const eo = computed(() => {
@@ -89,8 +105,8 @@ export default function useOptions (props, context, dep)
const fo = computed(() => {
let options = eo.value
- if (createdTag.value.length) {
- options = createdTag.value.concat(options)
+ if (createdOption.value.length) {
+ options = createdOption.value.concat(options)
}
options = filterOptions(options)
@@ -120,7 +136,7 @@ export default function useOptions (props, context, dep)
})
const noOptions = computed(() => {
- return !eo.value.length && !resolving.value && !createdTag.value.length
+ return !eo.value.length && !resolving.value && !createdOption.value.length
})
@@ -129,8 +145,8 @@ export default function useOptions (props, context, dep)
})
// no export
- const createdTag = computed(() => {
- if (createTag.value === false || !search.value) {
+ const createdOption = computed(() => {
+ if (createOption.value === false || !search.value) {
return []
}
@@ -270,6 +286,8 @@ export default function useOptions (props, context, dep)
return
}
+ handleOptionAppend(option)
+
blur()
select(option)
break
@@ -284,6 +302,8 @@ export default function useOptions (props, context, dep)
return
}
+ handleOptionAppend(option)
+
select(option)
if (clearOnSelect.value) {
@@ -312,15 +332,7 @@ export default function useOptions (props, context, dep)
return
}
- if (getOption(option[valueProp.value]) === undefined && createTag.value) {
- context.emit('tag', option[valueProp.value])
-
- if (appendNewTag.value) {
- appendOption(option)
- }
-
- clearSearch()
- }
+ handleOptionAppend(option)
if (clearOnSelect.value) {
clearSearch()
@@ -373,6 +385,19 @@ export default function useOptions (props, context, dep)
}
}
+ const handleOptionAppend = (option) => {
+ if (getOption(option[valueProp.value]) === undefined && createOption.value) {
+ context.emit('tag', option[valueProp.value])
+ context.emit('option', option[valueProp.value])
+
+ if (appendNewOption.value) {
+ appendOption(option)
+ }
+
+ clearSearch()
+ }
+ }
+
const selectAll = () => {
if (mode.value === 'single') {
return
diff --git a/tests/unit/composables/useKeyboard.spec.js b/tests/unit/composables/useKeyboard.spec.js
index f42ca5e..3592318 100644
--- a/tests/unit/composables/useKeyboard.spec.js
+++ b/tests/unit/composables/useKeyboard.spec.js
@@ -12,7 +12,7 @@ describe('useKeyboard', () => {
options: [],
mode: 'tags',
searchable: true,
- createTag: true,
+ createOption: true,
showOptions: false,
})
@@ -119,7 +119,7 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual(2)
})
- it('should not select pointer when mode=tags and createTag and addTagOn does not contain enter', async () => {
+ it('should not select pointer when mode=tags and createTag and addOptionTag does not contain enter', async () => {
let select = createSelect({
mode: 'tags',
value: [],
@@ -137,7 +137,7 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([])
})
- it('should select pointer when mode=tags and createTag and addTagOn does contain enter', async () => {
+ it('should select pointer when mode=tags and createTag and addOptionTag does contain enter', async () => {
let select = createSelect({
mode: 'tags',
value: [],
@@ -154,6 +154,42 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([2])
})
+
+ it('should not select pointer when mode=single and createOption and addOptionOn does not contain enter', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: null,
+ options: [1,2,3],
+ addOptionOn: ['space'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, 'enter')
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(null)
+ })
+
+ it('should select pointer when mode=single and createOption and addOptionOn does contain enter', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: null,
+ options: [1,2,3],
+ addOptionOn: ['space', 'enter'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, 'enter')
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(2)
+ })
})
describe('esc', () => {
@@ -261,6 +297,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1,2])
})
+ it('should select pointer if not searchable and createOption and single and addOptionOn contains space', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: ['space'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, 'space')
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(2)
+ })
+
it('should select pointer if searchable and createTag and tags and addTagOn contains space', async () => {
let select = createSelect({
mode: 'tags',
@@ -280,6 +334,25 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1, 2])
})
+ it('should select pointer if searchable and createOption and single and addOptionOn contains space', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ searchable: true,
+ addOptionOn: ['space'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, 'space')
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(2)
+ })
+
it('should not select pointer if not searchable and createTag and tags and addTagOn does not contain space', async () => {
let select = createSelect({
mode: 'tags',
@@ -298,6 +371,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1])
})
+ it('should not select pointer if not searchable and createOption and single and addOptionOn does not contain space', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: ['enter'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, 'space')
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(1)
+ })
+
it('should not select pointer if searchable and createTag and tags and addTagOn does not contain space', async () => {
let select = createSelect({
mode: 'tags',
@@ -316,6 +407,25 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1])
})
+
+ it('should not select pointer if searchable and createOption and single and addOptionOn does not contain space', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ searchable: true,
+ addOptionOn: ['enter'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, 'space')
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(1)
+ })
})
describe('up', () => {
@@ -432,6 +542,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1])
})
+ it('should not do anything when if mode=single and addOptionOn contains ; but createOption is false', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: [';'],
+ createOption: false,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, { key: ';' })
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(1)
+ })
+
it('should not do anything when if mode=tags and addTagOn does not contain ;', async () => {
let select = createSelect({
mode: 'tags',
@@ -450,6 +578,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1])
})
+ it('should not do anything when if mode=tags and addOptionOn does not contain ;', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: [','],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, { key: ';' })
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(1)
+ })
+
it('should select pointer if mode=tags and addTagOn contains ;', async () => {
let select = createSelect({
mode: 'tags',
@@ -467,6 +613,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1,2])
})
+
+ it('should select pointer if mode=single and addOptionOn contains ;', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: [';'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, { key: ';' })
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(2)
+ })
})
describe('comma', () => {
@@ -503,6 +667,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1])
})
+ it('should not do anything when if mode=single and addOptionOn contains , but createOption is false', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: [','],
+ createOption: false,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, { key: ',' })
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(1)
+ })
+
it('should not do anything when if mode=tags and addTagOn does not contain ,', async () => {
let select = createSelect({
mode: 'tags',
@@ -521,6 +703,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1])
})
+ it('should not do anything when if mode=single and addOptionOn does not contain ,', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: [';'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, { key: ',' })
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(1)
+ })
+
it('should select pointer if mode=tags and addTagOn contains ,', async () => {
let select = createSelect({
mode: 'tags',
@@ -538,6 +738,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1,2])
})
+
+ it('should select pointer if mode=single and addTagOn contains ,', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addTagOn: [','],
+ createTag: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, { key: ',' })
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(2)
+ })
})
describe('tab', () => {
@@ -574,6 +792,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1])
})
+ it('should not do anything when if mode=single and addOptionOn contains tab but createOption is false', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: ['tab'],
+ createOption: false,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, { key: 'Tab' })
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(1)
+ })
+
it('should not do anything when if mode=tags and addTagOn does not contain tab', async () => {
let select = createSelect({
mode: 'tags',
@@ -592,6 +828,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1])
})
+ it('should not do anything when if mode=single and addOptionOn does not contain tab', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: ['enter'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, { key: 'Tab' })
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(1)
+ })
+
it('should select pointer if mode=tags and addTagOn contains tab', async () => {
let select = createSelect({
mode: 'tags',
@@ -609,6 +863,24 @@ describe('useKeyboard', () => {
expect(getValue(select)).toStrictEqual([1,2])
})
+
+ it('should select pointer if mode=single and addOptionOn contains tab', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: 1,
+ options: [1,2,3],
+ addOptionOn: ['tab'],
+ createOption: true,
+ })
+
+ select.vm.setPointer(select.vm.getOption(2))
+
+ keydown(select, { key: 'Tab' })
+
+ await nextTick()
+
+ expect(getValue(select)).toStrictEqual(2)
+ })
})
})
})
\ No newline at end of file
diff --git a/tests/unit/composables/useOptions.spec.js b/tests/unit/composables/useOptions.spec.js
index 66805fe..9c88f2b 100644
--- a/tests/unit/composables/useOptions.spec.js
+++ b/tests/unit/composables/useOptions.spec.js
@@ -63,7 +63,7 @@ describe('useOptions', () => {
])
})
- it('should append createdTag to `fo` when createTag true', () => {
+ it('should append createdOption to `fo` when createTag true', () => {
const select = createSelect({
mode: 'tags',
createTag: true,
@@ -76,7 +76,7 @@ describe('useOptions', () => {
expect(select.vm.fo[0].v).toStrictEqual('new-tag')
})
- it('should not append createdTag to `fo` when if it already exists exists', () => {
+ it('should not append createdOption to `fo` when if it already exists exists', () => {
const select = createSelect({
mode: 'tags',
createTag: true,
@@ -981,7 +981,7 @@ describe('useOptions', () => {
describe('noResults', () => {
it('should be true if no options match search', () => {
let select = createSelect({
- options: ['Java', 'Javascript']
+ options: ['Java', 'Javascript'],
})
select.vm.search = 'jav'
expect(select.vm.noResults).toBe(false)
@@ -1602,6 +1602,101 @@ describe('useOptions', () => {
destroy(select)
})
+ it('should emit option and clear search and not append option on select if createOption true and option does not exist', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: null,
+ options: [1,2,3],
+ createOption: true,
+ appendNewOption: false,
+ object: true,
+ valueProp: 'v'
+ })
+
+ select.vm.search = 'value'
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ expect(select.emitted('option')[0][0]).toStrictEqual('value')
+ expect(select.vm.search).toBe('')
+ expect(select.vm.fo.length).toBe(3)
+ })
+
+ it('should append option if createOption && appendNewOption true and option does not exist', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: null,
+ options: [1,2,3],
+ createOption: true,
+ appendNewOption: true,
+ hideSelected: false,
+ valueProp: 'v'
+ })
+
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ expect(select.emitted('option')[0][0]).toStrictEqual('value')
+ expect(select.vm.fo).toStrictEqual([
+ { v: 1, label: 1 },
+ { v: 2, label: 2 },
+ { v: 3, label: 3 },
+ { v: 'value', label: 'value' },
+ ])
+ })
+
+ it('should not append option if it already exists', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: null,
+ options: [1,2,3],
+ createOption: true,
+ appendNewOption: true,
+ hideSelected: false,
+ valueProp: 'v',
+ })
+
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ expect(select.vm.fo).toStrictEqual([
+ { v: 1, label: 1 },
+ { v: 2, label: 2 },
+ { v: 3, label: 3 },
+ { v: 'value', label: 'value' },
+ ])
+ })
+
+ it('should not append option if appendNewOption is false', async () => {
+ let select = createSelect({
+ mode: 'single',
+ value: null,
+ options: [1,2,3],
+ createOption: true,
+ appendNewOption: false,
+ hideSelected: false,
+ object: true,
+ valueProp: 'v',
+ })
+
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ expect(select.vm.fo).toStrictEqual([
+ { v: 1, label: 1 },
+ { v: 2, label: 2 },
+ { v: 3, label: 3 },
+ ])
+ })
+
/* MULTISELECT */
it('should remove option from value if selected when multiple', async () => {
@@ -1712,6 +1807,101 @@ describe('useOptions', () => {
expect(select.vm.pointer).toStrictEqual(select.vm.getOption(2))
})
+ it('should emit option and clear search and not append option on select if createOption true and option does not exist', async () => {
+ let select = createSelect({
+ mode: 'multiple',
+ value: [],
+ options: [1,2,3],
+ createOption: true,
+ appendNewOption: false,
+ object: true,
+ valueProp: 'v'
+ })
+
+ select.vm.search = 'value'
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ expect(select.emitted('option')[0][0]).toStrictEqual('value')
+ expect(select.vm.search).toBe('')
+ expect(select.vm.fo.length).toBe(3)
+ })
+
+ it('should append option if createOption && appendNewOption true and option does not exist', async () => {
+ let select = createSelect({
+ mode: 'multiple',
+ value: [],
+ options: [1,2,3],
+ createOption: true,
+ appendNewOption: true,
+ hideSelected: false,
+ valueProp: 'v'
+ })
+
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ expect(select.emitted('option')[0][0]).toStrictEqual('value')
+ expect(select.vm.fo).toStrictEqual([
+ { v: 1, label: 1 },
+ { v: 2, label: 2 },
+ { v: 3, label: 3 },
+ { v: 'value', label: 'value' },
+ ])
+ })
+
+ it('should not append option if it already exists', async () => {
+ let select = createSelect({
+ mode: 'multiple',
+ value: [],
+ options: [1,2,3],
+ createOption: true,
+ appendNewOption: true,
+ hideSelected: false,
+ valueProp: 'v',
+ })
+
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ expect(select.vm.fo).toStrictEqual([
+ { v: 1, label: 1 },
+ { v: 2, label: 2 },
+ { v: 3, label: 3 },
+ { v: 'value', label: 'value' },
+ ])
+ })
+
+ it('should not append option if appendNewOption is false', async () => {
+ let select = createSelect({
+ mode: 'multiple',
+ value: [],
+ options: [1,2,3],
+ createOption: true,
+ appendNewOption: false,
+ hideSelected: false,
+ object: true,
+ valueProp: 'v',
+ })
+
+ select.vm.handleOptionClick({ v: 'value', label: 'value' })
+
+ await nextTick()
+
+ expect(select.vm.fo).toStrictEqual([
+ { v: 1, label: 1 },
+ { v: 2, label: 2 },
+ { v: 3, label: 3 },
+ ])
+ })
+
it('should blur input after select if closeOnSelect=true && mode=multiple', async () => {
let select = createSelect({
mode: 'multiple',