Skip to content

Commit

Permalink
Fix for #39 #40
Browse files Browse the repository at this point in the history
  • Loading branch information
adamberecz committed Mar 13, 2021
1 parent 2b4dc3a commit fc86d2f
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 9 deletions.
29 changes: 22 additions & 7 deletions src/composables/useOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import normalize from './../utils/normalize'
import isObject from './../utils/isObject'
import isNullish from './../utils/isNullish'
import arraysEqual from './../utils/arraysEqual'
import arrayObjectsEqual from './../utils/arrayObjectsEqual'

export default function useOptions (props, context, dependencies)
{
const { options, mode, trackBy, limit, hideSelected, createTag, label,
appendNewTag, multipleLabel, object, loading, delay, resolveOnLoad,
minChars, filterResults, clearOnSearch, clearOnSelect, valueProp,
canDeselect, max } = toRefs(props)
const {
options, mode, trackBy, limit, hideSelected, createTag, label,
appendNewTag, multipleLabel, object, loading, delay, resolveOnLoad,
minChars, filterResults, clearOnSearch, clearOnSelect, valueProp,
canDeselect, max
} = toRefs(props)

// ============ DEPENDENCIES ============

Expand Down Expand Up @@ -425,20 +428,32 @@ export default function useOptions (props, context, dependencies)
}, { flush: 'sync' })

watch(extendedOptions, (n, o) => {
if (!extendedOptions.value.length || !currentValue.value || !currentValue.value.length) {
if (!Object.keys(internalValue.value).length) {
initInternalValue()
}

if (!n.length || !currentValue.value || !currentValue.value.length) {
return
}

let newValue

if (mode.value === 'single') {
newValue = extendedOptions.value[extendedOptions.value.map(v=>v[valueProp.value]).indexOf(currentValue.value)]
newValue = n[n.map(v=>v[valueProp.value]).indexOf(currentValue.value)]

if (JSON.stringify(newValue) === JSON.stringify(internalValue.value)) {
return
}
} else {
newValue = []

currentValue.value.forEach((val) => {
newValue.push(extendedOptions.value[extendedOptions.value.map(v=>v[valueProp.value]).indexOf(val)])
newValue.push(n[n.map(v=>v[valueProp.value]).indexOf(val)])
})

if (arrayObjectsEqual(newValue, internalValue.value)) {
return
}
}

// Update both internal and external value if user is using object values
Expand Down
26 changes: 26 additions & 0 deletions src/utils/arrayObjectsEqual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const BreakException = {}

export default function arrayObjectsEqual (array1, array2) {
let equal = array1.length === array2.length

if (!equal) {
return equal
}

try {
array1.every(function(value, index) {
if (JSON.stringify(value) !== JSON.stringify(array2[index])) {
throw BreakException
}
})
} catch (e) {
/* istanbul ignore else */
if (e === BreakException) {
equal = false
} else {
throw e
}
}

return equal
}
20 changes: 18 additions & 2 deletions tests/unit/composables/useOptions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ describe('useOptions', () => {
expect(select.vm.filteredOptions[2].label).toBe(3)
})

it('should reactively changes label when options has been changed mode=single', async () => {
it('should reactively changes label when options has been changed mode=single, object=false', async () => {
let select = createSelect({
value: 'ru',
label: 'name',
Expand All @@ -155,7 +155,23 @@ describe('useOptions', () => {
expect(select.find('.multiselect-single-label').html()).toContain('Россия')
})

it('should reactively changes label when options has been changed mode=tags', async () => {
it('should not update value when options changed but did not affect value mode=single, object=false', async () => {
let select = createSelect({
value: 'ru',
label: 'name',
valueProp: 'code',
options: [{ code: 'au', name: 'Australia' }, { code: 'ru', name: 'Russia' }, { code: 'us', name: 'USA' }],
})

select.vm.$parent.props.options = [{ code: 'au', name: 'Australia' }, { code: 'ru', name: 'Russia' }]

await nextTick()

expect(select.find('.multiselect-single-label').element).toBeVisible()
expect(select.find('.multiselect-single-label').html()).toContain('Russia')
})

it('should reactively changes label when options has been changed mode=tags, object=false', async () => {
let select = createSelect({
mode: 'tags',
value: ['ru', 'au'],
Expand Down
7 changes: 7 additions & 0 deletions tests/unit/utils/arrayObjectsEqual.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import arrayObjectsEqual from './../../../src/utils/arrayObjectsEqual'

describe('arrayObjectsEqual', () => {
it('should return false if arrays are not same length', () => {
expect(arrayObjectsEqual([1],[1,2])).toBe(false)
})
})

0 comments on commit fc86d2f

Please sign in to comment.