我可以在 Shadow DOM 中获得一个按钮来提交不在 Shadow DOM 中的表单吗?
Can I get a button in Shadow DOM to submit a form not in Shadow DOM?
我只是 运行 遇到一个有趣的情况,我在放置在 <form>
内的本机自定义元素的 Shadow DOM 内有一个提交 <button>
。
<form id="one" action="" method="get">
<s-button>Select</s-button>
#shadow-root
<button>...</button>
<button>Outside</button>
</form>
我还有一个<button>
作为<form>
的直接child。
child <button>
导致表单提交。
但是 shadow-root 中的 <button>
没有。
在某种程度上,我想这是有道理的。但是有没有人想出一种方法来告诉 shadow-root <button>
与 <form>
一起正常工作,或者这是我必须通过 JS 处理的事情吗?
我知道点击事件在 Shadow DOM 层被阻止了,但我很惊讶没有办法让按钮仍然是表单的一部分,可以通过以下方式设置属性或 属性.
当然我可以捕获点击事件,然后从 this
发送一个新事件,但这不会做同样的事情,因为我的事件将不再是用户生成的,并且有大量相关的规则
无论如何你都必须通过Javascript来处理它。
一个简单的解决方案是在灯光DOM中添加一个(屏蔽)<button>
,并将click
事件传递给它。
customElements.define( 's-button', class extends HTMLElement {
connectedCallback() {
this.attachShadow( {mode: 'open'})
.innerHTML = `<button>In Shadow</button>`
var submit = this.appendChild( document.createElement( 'button' ) )
this.onclick = () => submit.click()
}
} )
<form onsubmit="console.log('submitted');return false">
<s-button>Select</s-button>
<button>Outside</button>
</form>
一个按钮触发一个 submit Event(在 FORM 元素上)
因为 Events 不能通过阴影 DOM 边界(不要冒泡到父级 DOM)
我推测这就是为什么 FORM 元素没有接收到影子DOM 按钮(调度 submit
事件)的原因。
需要 Supersharps 解决方法,在灯 DOM 中使用隐藏按钮(然后在父 DOM 中调度 submit
事件)
或者(从 light DOM 开始)您找到(父)FORM 标签并自己发送一个提交事件:
this.closest('FORM').dispatchEvent(new Event('submit'))
关注影子DOM 和 FORM 方面的专家:https://github.com/w3c/webcomponents/issues/187
customElements.define( 'my-button', class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode:'open'}).innerHTML=`<button>Button In Shadow DOM</button>`
this.onclick = _ => this.closest('FORM').dispatchEvent(new Event('submit'))
}
})
<form onsubmit="return console.log('submit Event occured')">
<my-button></my-button>
<button>button in Document DOM</button>
</form>
嵌套阴影DOMs
如果 FORM 不是直接祖先,您可以通过类似以下内容找到它:
您可以做的其他事情不是完全阴影中的按钮DOM,而是如果您的button[type=submit]
已插入阴影DOM。所以如果你有类似的东西:
<some-component>
<button type="submit" slot="buttonSlot"></button>
</some-component>
该按钮可用于触发您的表单。
该按钮在灯光 DOM 中,但可以通过插槽从您的组件内轻松处理。它还将毫无问题地保留所有适当的键盘、单击、焦点等事件。
为了最小化光线 DOM html 你甚至不需要它是一个 type=submit
你可以在你的组件中设置它,它仍然会被视为DOM.
中任何父表单的提交按钮
额外的好处(或者可能是麻烦,这取决于您如何看待它),它将保留页面上其他按钮的样式(除非您在组件中更改它)。
我只是 运行 遇到一个有趣的情况,我在放置在 <form>
内的本机自定义元素的 Shadow DOM 内有一个提交 <button>
。
<form id="one" action="" method="get">
<s-button>Select</s-button>
#shadow-root
<button>...</button>
<button>Outside</button>
</form>
我还有一个<button>
作为<form>
的直接child。
child <button>
导致表单提交。
但是 shadow-root 中的 <button>
没有。
在某种程度上,我想这是有道理的。但是有没有人想出一种方法来告诉 shadow-root <button>
与 <form>
一起正常工作,或者这是我必须通过 JS 处理的事情吗?
我知道点击事件在 Shadow DOM 层被阻止了,但我很惊讶没有办法让按钮仍然是表单的一部分,可以通过以下方式设置属性或 属性.
当然我可以捕获点击事件,然后从 this
发送一个新事件,但这不会做同样的事情,因为我的事件将不再是用户生成的,并且有大量相关的规则
无论如何你都必须通过Javascript来处理它。
一个简单的解决方案是在灯光DOM中添加一个(屏蔽)<button>
,并将click
事件传递给它。
customElements.define( 's-button', class extends HTMLElement {
connectedCallback() {
this.attachShadow( {mode: 'open'})
.innerHTML = `<button>In Shadow</button>`
var submit = this.appendChild( document.createElement( 'button' ) )
this.onclick = () => submit.click()
}
} )
<form onsubmit="console.log('submitted');return false">
<s-button>Select</s-button>
<button>Outside</button>
</form>
一个按钮触发一个 submit Event(在 FORM 元素上)
因为 Events 不能通过阴影 DOM 边界(不要冒泡到父级 DOM)
我推测这就是为什么 FORM 元素没有接收到影子DOM 按钮(调度 submit
事件)的原因。
需要 Supersharps 解决方法,在灯 DOM 中使用隐藏按钮(然后在父 DOM 中调度 submit
事件)
或者(从 light DOM 开始)您找到(父)FORM 标签并自己发送一个提交事件:
this.closest('FORM').dispatchEvent(new Event('submit'))
关注影子DOM 和 FORM 方面的专家:https://github.com/w3c/webcomponents/issues/187
customElements.define( 'my-button', class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode:'open'}).innerHTML=`<button>Button In Shadow DOM</button>`
this.onclick = _ => this.closest('FORM').dispatchEvent(new Event('submit'))
}
})
<form onsubmit="return console.log('submit Event occured')">
<my-button></my-button>
<button>button in Document DOM</button>
</form>
嵌套阴影DOMs
如果 FORM 不是直接祖先,您可以通过类似以下内容找到它:
您可以做的其他事情不是完全阴影中的按钮DOM,而是如果您的button[type=submit]
已插入阴影DOM。所以如果你有类似的东西:
<some-component>
<button type="submit" slot="buttonSlot"></button>
</some-component>
该按钮可用于触发您的表单。 该按钮在灯光 DOM 中,但可以通过插槽从您的组件内轻松处理。它还将毫无问题地保留所有适当的键盘、单击、焦点等事件。
为了最小化光线 DOM html 你甚至不需要它是一个 type=submit
你可以在你的组件中设置它,它仍然会被视为DOM.
额外的好处(或者可能是麻烦,这取决于您如何看待它),它将保留页面上其他按钮的样式(除非您在组件中更改它)。