Skip to content

Commit 959ded2

Browse files
authored
fix(runtime-dom): handle activeElement check in Shadow DOM for v-model (#14196)
1 parent 560def4 commit 959ded2

2 files changed

Lines changed: 52 additions & 1 deletion

File tree

packages/runtime-dom/__tests__/directives/vModel.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,52 @@ describe('vModel', () => {
375375
expect(data.lazy).toEqual('foo')
376376
})
377377

378+
it('should preserve unresolved trimmed text while focused in nested shadow roots', async () => {
379+
const model = ref('')
380+
const component = defineComponent({
381+
render() {
382+
return withVModel(
383+
h('input', {
384+
'onUpdate:modelValue': (value: string) => {
385+
model.value = value
386+
},
387+
}),
388+
model.value,
389+
{
390+
trim: true,
391+
},
392+
)
393+
},
394+
})
395+
396+
document.body.appendChild(root)
397+
const outerShadowRoot = root.attachShadow({ mode: 'open' })
398+
const innerHost = document.createElement('div')
399+
outerShadowRoot.appendChild(innerHost)
400+
const innerShadowRoot = innerHost.attachShadow({ mode: 'open' })
401+
402+
try {
403+
render(h(component), innerShadowRoot)
404+
405+
const input = innerShadowRoot.querySelector('input') as HTMLInputElement
406+
input.focus()
407+
408+
expect(document.activeElement).toBe(root)
409+
expect(outerShadowRoot.activeElement).toBe(innerHost)
410+
expect(innerShadowRoot.activeElement).toBe(input)
411+
412+
input.value = ' hello, world '
413+
triggerEvent('input', input)
414+
await nextTick()
415+
416+
expect(model.value).toEqual('hello, world')
417+
expect(input.value).toEqual(' hello, world ')
418+
} finally {
419+
render(null, innerShadowRoot)
420+
root.remove()
421+
}
422+
})
423+
378424
it('should work with range', async () => {
379425
const component = defineComponent({
380426
data() {

packages/runtime-dom/src/directives/vModel.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,12 @@ export const vModelText: ModelDirective<
102102
return
103103
}
104104

105-
if (document.activeElement === el && el.type !== 'range') {
105+
const rootNode = el.getRootNode()
106+
if (
107+
(rootNode instanceof Document || rootNode instanceof ShadowRoot) &&
108+
rootNode.activeElement === el &&
109+
el.type !== 'range'
110+
) {
106111
// #8546
107112
if (lazy && value === oldValue) {
108113
return

0 commit comments

Comments
 (0)