Skip to content

Commit

Permalink
fix some infinite scroll issues (#54)
Browse files Browse the repository at this point in the history
* fix: loadMore is only emitted once

* fix: multiselect isn't cleared if options are removed in infinite mode

* fix: don't emit 'loadMore' if options are currently loading

* feat: performance rework

* fix: if-condition

* fix: remember selected options in infinite mode

* chore: remove duplicate code

* chore: remove unnecessary comments

Co-authored-by: Merlin Flach <merlin.flach@singular-it.de>
  • Loading branch information
2 people authored and Tim Streicher committed Dec 7, 2022
1 parent fdcd3e3 commit 23b767b
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 154 deletions.
27 changes: 5 additions & 22 deletions src/Multiselect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@mousedown.self="handleMousedown"
>
<select
v-model="selectedValues"
v-model="selectedOptionsRef"
:multiple="multiple"
v-bind="selectProps"
class="hidden"
Expand All @@ -24,7 +24,6 @@
:class="classList.search"
v-bind="searchProps"
data-cy="search-input"
@input="handleInput"
>
</template>

Expand Down Expand Up @@ -144,13 +143,11 @@

<script lang="ts">
import type {InputHTMLAttributes, PropType, SelectHTMLAttributes, SetupContext} from 'vue'
import {defineComponent, toRefs, watch} from 'vue'
import * as _ from 'lodash'
import {defineComponent, toRefs} from 'vue'
import useMultiselect from './utils/useMultiselect'
import useDropdown from './utils/useDropdown'
import useSearch from './utils/useSearch'
import useOptions from './utils/useOptions'
import useValue from './utils/useValue'
import useClasses from './utils/useClasses'
import type {Classes, Option} from './types'
import useScroll from './utils/useScroll'
Expand Down Expand Up @@ -404,17 +401,15 @@ export default defineComponent({
setup(props, context: SetupContext) {
const {
multiple, modelValue, searchable, disabled, closeOnSelect, selectOptions, displaySelectedValues,
optionValue, optionLabel, optionDisabled, optionSearchValue, classes, infinite, maxOptions,
optionValue, optionLabel, optionDisabled, optionSearchValue, classes, infinite, maxOptions, loadingOptions,
} = toRefs(props)
const value = useValue(multiple, modelValue)
const dropdown = useDropdown(context)
const search = useSearch(context)
const multiselect = useMultiselect(
searchable,
disabled,
multiple,
context,
value.selectedValues,
dropdown.openDropdown,
dropdown.closeDropdown,
search.clearSearch,
Expand All @@ -431,14 +426,15 @@ export default defineComponent({
optionLabel,
optionDisabled,
optionSearchValue,
infinite,
context,
value.selectedValues,
multiselect.deactivate,
search.search,
)
const scroll = useScroll(
infinite,
maxOptions,
loadingOptions,
selectOptions,
context,
)
Expand All @@ -452,20 +448,7 @@ export default defineComponent({
multiselect.isActive,
)
watch(() => props.selectOptions, (newOptions, oldOptions) => {
if (newOptions && newOptions.length > 0) {
for (const option of oldOptions) {
if (!_.some(newOptions, option as never) && options.isSelected(option, options.selectedOptions.value))
options.deselect(option)
}
}
else {
multiselect.clear()
}
})
return {
...value,
...dropdown,
...search,
...options,
Expand Down
2 changes: 1 addition & 1 deletion src/stories/MultiselectTester.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ const Template = args => ({
export const TesterComponent = Template.bind({})
TesterComponent.args = {
placeholder: 'huhu',
selectOptions: [{value: 1, label: 'Wie'}, {value: 'hallo', label: 'geht'}, {value: {nested: 'juhu'}, label: 'es'}, {value: true, label: 'dir'}],
selectOptions: [{value: 1, label: 'Wie'}, {value: 'hallo', label: 'geht'}, {value: {nested: 'juhu'}, label: 'es'}, {value: true, label: 'dir'}, {value: 3, label: 'du'}, {value: 4, label: 'bist'}, {value: 5, label: 'ganz'}, {value: 6, label: 'schön'}, {value: 7, label: 'cool'}],
vModel: true,
}
21 changes: 18 additions & 3 deletions src/tests/MultiselectTester.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@
Change select Options
</button>
</div>
<div v-if="infinite && dynamicOptions">
<button
class="mt-4 text-center w-full border-2 bg-gray-100"
data-cy="changeOptionsButton"
@click="addOption"
>
Add option with illegal value
</button>
</div>
<div v-if="testExposedFunctions">
<button
class="mt-4 text-center w-full border-2 bg-gray-100"
Expand Down Expand Up @@ -274,7 +283,7 @@ export default defineComponent({
value = [value]
selected.value = value
}
else if (setValue.value && !multiple.value) {
else if (!multiple.value) {
selected.value = value
}
else if (!setValue.value && Array.isArray(selected.value)) {
Expand All @@ -291,7 +300,7 @@ export default defineComponent({
selected.value = [value, secondValue]
}
else if (setValue.value && !multiple.value) {
else if (!multiple.value) {
selected.value = value
}
Expand All @@ -301,7 +310,7 @@ export default defineComponent({
}
}
const dynamicSelectOptions = ref<Option[]>([
const dynamicSelectOptions = ref<Array<Option | unknown>>([
{value: {abc: 'xyz', test: {xyz: 3}}, label: 'This'},
{value: 2, label: 'is'},
{value: 'haha', label: 'a'},
Expand All @@ -315,6 +324,11 @@ export default defineComponent({
]
}
function addOption() {
const option = {value: {this: 'Hallo', is: 1234, a: {Test: 'okayyy, let\'s go'}}, label: 'jooooooo'}
dynamicSelectOptions.value.push(option)
}
const multiselect = ref<typeof Multiselect | null>(null)
function testFocus() {
Expand All @@ -333,6 +347,7 @@ export default defineComponent({
pushIllegalValue,
dynamicSelectOptions,
changeSelectOptions,
addOption,
testFocus,
testBlur,
multiselect,
Expand Down
1 change: 0 additions & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ export {default as useDropdown} from './useDropdown'
export {default as useMultiselect} from './useMultiselect'
export {default as useOptions} from './useOptions'
export {default as useSearch} from './useSearch'
export {default as useValue} from './useValue'
13 changes: 0 additions & 13 deletions src/utils/useMultiselect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export default function useMultiselect(searchable: Ref<boolean>,
disabled: Ref<boolean>,
multiple: Ref<boolean>,
context: SetupContext,
selectedValues: Ref,
openDropdown: () => void,
closeDropdown: () => void,
clearSearch: () => void,
Expand Down Expand Up @@ -36,17 +35,6 @@ export default function useMultiselect(searchable: Ref<boolean>,
}
}

function clear() {
if (multiple.value)
selectedValues.value.length = 0
else
selectedValues.value = null

deactivate()
context.emit('update:modelValue', selectedValues.value)
context.emit('clear')
}

function handleFocus() {
input.value?.focus()
}
Expand Down Expand Up @@ -80,7 +68,6 @@ export default function useMultiselect(searchable: Ref<boolean>,
tabindex,
activate,
deactivate,
clear,
handleMousedown,
handleFocus,
}
Expand Down
Loading

0 comments on commit 23b767b

Please sign in to comment.