Skip to content

Commit be91254

Browse files
authored
fix(directive.js): fix handling events for multiple elements (#41)
Problem: If two input elements with the v-facade directive are both in the same root element, then the event handlers for each will trigger for ALL inputs on the elements. This can be problematic in cases where an input event cannot or should not be handled by the masking function, ie when one input is masked and the other is not. Solution: Add a check to the event handler to confirm that the event target is in fact the element that was initially target by the v-facade we care about.
1 parent d6aaf66 commit be91254

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

src/directive.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ export default {
1919
const handlerOwner = el.parentElement || el
2020

2121
// use anonymous event handler to avoid inadvertently removing masking for all inputs within a container
22-
const handler = (e) => core.inputHandler(e)
22+
const handler = (e) => {
23+
if (e.target !== el) {
24+
return
25+
}
26+
core.inputHandler(e, el)
27+
}
2328

2429
handlerOwner.addEventListener('input', handler, true)
2530

tests/directive.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ describe('Directive', () => {
2424

2525
afterEach(() => {
2626
jest.restoreAllMocks()
27+
inputListener.mockReset()
2728
wrapper && wrapper.destroy()
2829
})
2930

@@ -204,4 +205,41 @@ describe('Directive', () => {
204205
expect(wrapper.element.setSelectionRange).not.toBeCalled()
205206
})
206207
})
208+
209+
describe('multiple inputs, one facade', () => {
210+
let otherInput
211+
let facadeInput
212+
213+
beforeEach(() => {
214+
const template = `<div id="wrapper">
215+
<input id="first" v-facade="mask" value="" @input="inputListener" />
216+
<input id="second" />
217+
</div>`
218+
buildWrapper({ template })
219+
otherInput = wrapper.find('#second')
220+
facadeInput = wrapper.find('#first')
221+
})
222+
223+
test('should not emit for other inputs', async () => {
224+
otherInput.setValue('1122')
225+
226+
expect(otherInput.element.value).toBe('1122')
227+
expect(facadeInput.element.value).toBe('')
228+
expect(inputListener).toBeCalledTimes(0)
229+
})
230+
231+
test('should still handle inputs for the main element', async () => {
232+
facadeInput.setValue('1122')
233+
234+
expect(otherInput.element.value).toBe('')
235+
expect(facadeInput.element.value).toBe('11.22')
236+
237+
otherInput.setValue('2233')
238+
239+
expect(otherInput.element.value).toBe('2233')
240+
expect(facadeInput.element.value).toBe('11.22')
241+
242+
expect(inputListener).toBeCalledTimes(1)
243+
})
244+
})
207245
})

0 commit comments

Comments
 (0)