From dfe6590ad80f6e772dcf5aaaf821d97e4812a308 Mon Sep 17 00:00:00 2001 From: Maksym Cierzniak Date: Mon, 25 Jan 2021 23:37:19 +0100 Subject: [PATCH] [#511] * now directive will compare previous mask result with the current one if the binding value is a function when triggering update * `input` event will not fire if calculated masked value is the same as the value of the input --- src/__tests__/index.test.js | 11 +++++++++++ src/directive.js | 32 ++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/__tests__/index.test.js b/src/__tests__/index.test.js index db46180c..091c1a5a 100644 --- a/src/__tests__/index.test.js +++ b/src/__tests__/index.test.js @@ -243,6 +243,17 @@ describe('directive usage', () => { await wrapper.vm.$nextTick(); expect(wrapper.vm.$el.value).toBe('19:32'); }); + + it('should not trigger input events if resolved mask is the same as previous one', async () => { + const wrapper = mountWithMask({ + props: { triggerUpdate: { required: false } }, + data: () => ({ mask: () => [/\d/, /\d/], value: null }), + template: '', + }); + + await wrapper.setProps({ triggerUpdate: true }); + expect(wrapper.emitted().input).toBeFalsy(); + }); }); describe('filter usage', () => { diff --git a/src/directive.js b/src/directive.js index a778c97a..3952d8e0 100644 --- a/src/directive.js +++ b/src/directive.js @@ -20,6 +20,15 @@ function triggerInputUpdate(el) { trigger(el, 'input'); } +function updateElementWithMaskedValue(el, maskedValue) { + if (maskedValue === el.value) { + return; + } + + el.value = maskedValue; + triggerInputUpdate(el); +} + /** * Event handler * @param {HTMLInputElement} el @@ -35,8 +44,8 @@ function updateValue(el, force = false) { if ((force || isUpdateNeeded) && mask) { const { conformedValue } = conformToMask(value, mask, { guide: false }); - el.value = conformedValue; - triggerInputUpdate(el); + + updateElementWithMaskedValue(el, conformedValue); } options.partiallyUpdate(el, { previousValue: value }); @@ -95,6 +104,22 @@ function maskToString(mask) { return filteredMaskArray.toString(); } +/** + * Check if previous mask has been different than current one + * @param {String|Array.} mask + */ +function hasMaskFromBindingChanged(el, oldValue, currentValue) { + const previousMask = isFunction(oldValue) + ? maskToString(oldValue(options.get(el).previousValue)) + : maskToString(oldValue); + + const currentMask = isFunction(currentValue) + ? maskToString(currentValue(el.value)) + : maskToString(currentValue); + + return previousMask !== currentMask; +} + /** * Create the Vue directive * @param {Object} directiveOptions @@ -139,8 +164,7 @@ export function createDirective(directiveOptions = {}) { componentUpdated(el, { value, oldValue }) { el = queryInputElementInside(el); - const isMaskChanged = isFunction(value) - || maskToString(oldValue) !== maskToString(value); + const isMaskChanged = hasMaskFromBindingChanged(el, oldValue, value); if (isMaskChanged) { updateMask(el, value, instanceMaskReplacers);