mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-22 10:30:34 +03:00
feat: add deselectFromDropdown boolean prop (#1033)
This commit is contained in:
@@ -163,6 +163,17 @@ createOption: {
|
|||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## deselectFromDropdown <Badge text="v3.12.0+" />
|
||||||
|
|
||||||
|
Determines whether the user can deselect an option by clicking
|
||||||
|
it from within the dropdown menu.
|
||||||
|
|
||||||
|
```js
|
||||||
|
deselectFromDropdown: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
## dir
|
## dir
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,8 @@
|
|||||||
role="option"
|
role="option"
|
||||||
class="vs__dropdown-option"
|
class="vs__dropdown-option"
|
||||||
:class="{
|
:class="{
|
||||||
|
'vs__dropdown-option--deselect':
|
||||||
|
isOptionDeselectable(option) && index === typeAheadPointer,
|
||||||
'vs__dropdown-option--selected': isOptionSelected(option),
|
'vs__dropdown-option--selected': isOptionSelected(option),
|
||||||
'vs__dropdown-option--highlight': index === typeAheadPointer,
|
'vs__dropdown-option--highlight': index === typeAheadPointer,
|
||||||
'vs__dropdown-option--disabled': !selectable(option),
|
'vs__dropdown-option--disabled': !selectable(option),
|
||||||
@@ -206,6 +208,16 @@ export default {
|
|||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can the user deselect an option by clicking it from
|
||||||
|
* within the dropdown.
|
||||||
|
* @type {Boolean}
|
||||||
|
*/
|
||||||
|
deselectFromDropdown: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable/disable filtering the options.
|
* Enable/disable filtering the options.
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
@@ -960,7 +972,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select a given option.
|
* Select or deselect a given option.
|
||||||
|
* Allow deselect if clearable or if not the only selected option.
|
||||||
* @param {Object|String} option
|
* @param {Object|String} option
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
@@ -975,6 +988,11 @@ export default {
|
|||||||
}
|
}
|
||||||
this.updateValue(option)
|
this.updateValue(option)
|
||||||
this.$emit('option:selected', option)
|
this.$emit('option:selected', option)
|
||||||
|
} else if (
|
||||||
|
this.deselectFromDropdown &&
|
||||||
|
(this.clearable || (this.multiple && this.selectedValue.length > 1))
|
||||||
|
) {
|
||||||
|
this.deselect(option)
|
||||||
}
|
}
|
||||||
this.onAfterSelect(option)
|
this.onAfterSelect(option)
|
||||||
},
|
},
|
||||||
@@ -1090,6 +1108,13 @@ export default {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can the current option be removed via the dropdown?
|
||||||
|
*/
|
||||||
|
isOptionDeselectable(option) {
|
||||||
|
return this.isOptionSelected(option) && this.deselectFromDropdown
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if two option objects are matching.
|
* Determine if two option objects are matching.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ $vs-component-placeholder-color: inherit !default;
|
|||||||
$vs-state-active-bg: #5897fb !default;
|
$vs-state-active-bg: #5897fb !default;
|
||||||
$vs-state-active-color: #fff !default;
|
$vs-state-active-color: #fff !default;
|
||||||
|
|
||||||
|
// Deselect State
|
||||||
|
$vs-state-deselect-bg: #fb5858 !default;
|
||||||
|
$vs-state-deselect-color: #fff !default;
|
||||||
|
|
||||||
// Disabled State
|
// Disabled State
|
||||||
$vs-state-disabled-bg: rgb(248, 248, 248) !default;
|
$vs-state-disabled-bg: rgb(248, 248, 248) !default;
|
||||||
$vs-state-disabled-color: map_get($vs-colors, 'light') !default;
|
$vs-state-disabled-color: map_get($vs-colors, 'light') !default;
|
||||||
|
|||||||
@@ -14,6 +14,11 @@
|
|||||||
color: $vs-state-active-color;
|
color: $vs-state-active-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vs__dropdown-option--deselect {
|
||||||
|
background: $vs-state-deselect-bg;
|
||||||
|
color: $vs-state-deselect-color;
|
||||||
|
}
|
||||||
|
|
||||||
.vs__dropdown-option--disabled {
|
.vs__dropdown-option--disabled {
|
||||||
background: inherit;
|
background: inherit;
|
||||||
color: $vs-state-disabled-color;
|
color: $vs-state-disabled-color;
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ describe('Removing values', () => {
|
|||||||
it('will not emit input event if value has not changed with backspace', () => {
|
it('will not emit input event if value has not changed with backspace', () => {
|
||||||
const Select = mountDefault()
|
const Select = mountDefault()
|
||||||
Select.vm.$data._value = 'one'
|
Select.vm.$data._value = 'one'
|
||||||
|
|
||||||
Select.findComponent({ ref: 'search' }).trigger('keydown.backspace')
|
Select.findComponent({ ref: 'search' }).trigger('keydown.backspace')
|
||||||
expect(Select.emitted().input.length).toBe(1)
|
expect(Select.emitted().input.length).toBe(1)
|
||||||
|
|
||||||
@@ -59,6 +60,58 @@ describe('Removing values', () => {
|
|||||||
expect(Select.emitted().input.length).toBe(1)
|
expect(Select.emitted().input.length).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should deselect a selected option when clicked and deselectFromDropdown is true', async () => {
|
||||||
|
const Select = selectWithProps({
|
||||||
|
value: 'one',
|
||||||
|
options: ['one', 'two', 'three'],
|
||||||
|
deselectFromDropdown: true,
|
||||||
|
})
|
||||||
|
const deselect = spyOn(Select.vm, 'deselect')
|
||||||
|
|
||||||
|
Select.vm.open = true
|
||||||
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
|
Select.find('.vs__dropdown-option--selected').trigger('click')
|
||||||
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
|
expect(deselect).toHaveBeenCalledWith('one')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not deselect a selected option when clicked if clearable is false', async () => {
|
||||||
|
const Select = selectWithProps({
|
||||||
|
value: 'one',
|
||||||
|
options: ['one', 'two', 'three'],
|
||||||
|
clearable: false,
|
||||||
|
deselectFromDropdown: true,
|
||||||
|
})
|
||||||
|
const deselect = spyOn(Select.vm, 'deselect')
|
||||||
|
|
||||||
|
Select.vm.open = true
|
||||||
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
|
Select.find('.vs__dropdown-option--selected').trigger('click')
|
||||||
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
|
expect(deselect).not.toHaveBeenCalledWith('one')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not deselect a selected option when clicked if deselectFromDropdown is false', async () => {
|
||||||
|
const Select = selectWithProps({
|
||||||
|
value: 'one',
|
||||||
|
options: ['one', 'two', 'three'],
|
||||||
|
deselectFromDropdown: false,
|
||||||
|
})
|
||||||
|
const deselect = spyOn(Select.vm, 'deselect')
|
||||||
|
|
||||||
|
Select.vm.open = true
|
||||||
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
|
Select.find('.vs__dropdown-option--selected').trigger('click')
|
||||||
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
|
expect(deselect).not.toHaveBeenCalledWith('one')
|
||||||
|
})
|
||||||
|
|
||||||
describe('Clear button', () => {
|
describe('Clear button', () => {
|
||||||
it('should be displayed on single select when value is selected', () => {
|
it('should be displayed on single select when value is selected', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
|
|||||||
Reference in New Issue
Block a user