Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/components/form-input/form-input.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,33 @@ describe('form-input', () => {
// `input` event should not have emitted new event
expect(wrapper.emitted('input').length).toBe(4)

$input.element.value = 'abc'
await $input.trigger('input')
expect($input.element.value).toBe('abc')
// `v-model` update event should not have emitted new event
expect(wrapper.emitted('update').length).toBe(2)
// `input` event should be emitted
expect(wrapper.emitted('input').length).toBe(5)
expect(wrapper.emitted('input')[4][0]).toBe('abc')

$input.element.value = 'abcd'
await $input.trigger('input')
expect($input.element.value).toBe('abcd')
// `v-model` update event should not have emitted new event
expect(wrapper.emitted('update').length).toBe(2)
// `input` event should be emitted
expect(wrapper.emitted('input').length).toBe(6)
expect(wrapper.emitted('input')[5][0]).toBe('abcd')

// Advance timer
jest.runOnlyPendingTimers()
// Should update the v-model
expect($input.element.value).toBe('abcd')
// `v-model` update event should not have emitted new event
expect(wrapper.emitted('update').length).toBe(2)
// `input` event should not have emitted new event
expect(wrapper.emitted('input').length).toBe(6)

wrapper.destroy()
})

Expand Down
56 changes: 30 additions & 26 deletions src/mixins/form-text.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,35 +161,39 @@ export default {
if (lazy && !force) {
return
}
value = this.modifyValue(value)
if (value !== this.vModelValue) {
this.clearDebounce()
const doUpdate = () => {
// Make sure to always clear the debounce when `updateValue()`
// is called, even when the v-model hasn't changed
this.clearDebounce()
// Define the shared update logic in a method to be able to use
// it for immediate and debounced value changes
const doUpdate = () => {
value = this.modifyValue(value)
if (value !== this.vModelValue) {
this.vModelValue = value
this.$emit('update', value)
} else if (this.hasFormatter) {
// When the `vModelValue` hasn't changed but the actual input value
// is out of sync, make sure to change it to the given one
// Usually caused by browser autocomplete and how it triggers the
// change or input event, or depending on the formatter function
// https://github.com/bootstrap-vue/bootstrap-vue/issues/2657
// https://github.com/bootstrap-vue/bootstrap-vue/issues/3498
/* istanbul ignore next: hard to test */
const $input = this.$refs.input
/* istanbul ignore if: hard to test out of sync value */
if ($input && value !== $input.value) {
$input.value = value
}
}
const debounce = this.computedDebounce
// Only debounce the value update when a value greater than `0`
// is set and we are not in lazy mode or this is a forced update
if (debounce > 0 && !lazy && !force) {
this.$_inputDebounceTimer = setTimeout(doUpdate, debounce)
} else {
// Immediately update the v-model
doUpdate()
}
} else if (this.hasFormatter) {
// When the `vModelValue` hasn't changed but the actual input value
// is out of sync, make sure to change it to the given one
// Usually caused by browser autocomplete and how it triggers the
// change or input event, or depending on the formatter function
// https://github.com/bootstrap-vue/bootstrap-vue/issues/2657
// https://github.com/bootstrap-vue/bootstrap-vue/issues/3498
/* istanbul ignore next: hard to test */
const $input = this.$refs.input
/* istanbul ignore if: hard to test out of sync value */
if ($input && value !== $input.value) {
$input.value = value
}
}
// Only debounce the value update when a value greater than `0`
// is set and we are not in lazy mode or this is a forced update
const debounce = this.computedDebounce
if (debounce > 0 && !lazy && !force) {
this.$_inputDebounceTimer = setTimeout(doUpdate, debounce)
} else {
// Immediately update the v-model
doUpdate()
}
},
onInput(evt) {
Expand Down