[英]How can I create a web component that acts like a form element?
I am trying to create a web component that is usable in a form element specifically, that has a name
, and a value
. 我正在尝试创建一个特定于表单元素中可用的Web组件,它具有
name
和value
。 I recognize that I can create a web component that extends
an HTMLInputElement
: 我意识到我可以创建一个
extends
HTMLInputElement
的Web组件:
<input is="very-extended">
but I am trying to create an entirely new element. 但我正在努力创造一个全新的元素。
When creating a regular web component, you can create it from the prototype of a regular HTMLElement
( HTMLElement.prototype
). 创建常规Web组件时,可以从常规
HTMLElement
( HTMLElement.prototype
)的原型创建它。 Which leads me to assume that I can create a different element with the prototype of an HTMLInputElement
( HTMLInputElement.prototype
). 这让我想到我可以使用
HTMLInputElement
( HTMLInputElement.prototype
)的原型创建一个不同的元素。 You actually use that prototype when extending
the API of input elements, so why can't I use that prototype to create an entirely new element that works in a form? 在
extending
输入元素的API时extending
您实际上是使用该原型,那么为什么我不能使用该原型来创建一个在表单中工作的全新元素?
If you look at the shadow dom of a regular input field: 如果你看一下常规输入字段的阴影dom:
you can see that there is a div inside of there. 你可以看到里面有一个div。 I understand that this
HTMLInputElement
has methods and attributes, getters/setters, etc. So why is it that when I attempt to create my component, it fails to be part of the name, value pairs found in the form? 我知道这个
HTMLInputElement
有方法和属性,getter / setter等等。那么为什么当我尝试创建我的组件时,它不能成为表单中找到的名称,值对的一部分?
Here is an example of how I am trying to create this web component: 以下是我尝试创建此Web组件的示例:
Please note that his should be tested in a browser that supports web components. 请注意,他应该在支持Web组件的浏览器中进行测试。
(function() { var iconDoc = (document._currentScript || document.currentScript).ownerDocument; var objectPrototype = Object.create(HTMLInputElement.prototype); Object.defineProperty(objectPrototype, 'name', { writable: true }); Object.defineProperty(objectPrototype, 'value', { writable: true }); objectPrototype.createdCallback = function() { var shadow = this.createShadowRoot(); var template = iconDoc.querySelector('#test'); shadow.appendChild(template.content.cloneNode(true)); }; document.registerElement('custom-input', { prototype: objectPrototype }); })(); console.log( $('form').serialize() )
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <template id="test"> <div>This is a special input</div> </template> <form> <input name="regular" value="input"> <custom-input name="foo" value="bar"></custom-input> </form>
Why is the name, value pair not found among the form, and how can I create a custom form element? 为什么在表单中找不到名称,值对,以及如何创建自定义表单元素?
KevBot, KevBot,
You seem to think that the element includes itself in the form. 您似乎认为元素包含在表单中。 That is not the case.
事实并非如此。 It is the form that searches its children elements by tag name , to decide which elements it should include.
它是通过标记名称搜索其子元素的表单,以决定它应包含哪些元素。 It will simply ignore those with unknown tag names.
它将简单地忽略具有未知标签名称的那些。
Your custom-input
name is not among the elements the form searches. 您的
custom-input
名称不在表单搜索的元素中。 Therefore, it is not included on the form. 因此,它不包含在表格中。 It doesn't matter the custom element's prototype.
自定义元素的原型并不重要。 That's why it works if you use
is
, since then the tag name is maintained. 这就是为什么它可以使用
is
,从那时起,标签名称被维护。
Of course, you may implement your own custom-form
that behaves differently, if you want. 当然,如果需要,您可以实现自己的
custom-form
,其行为方式不同。
You can create your <custom-input>
custom element that will be interpreted by a form
, just by adding inside your template
a hidden input
element with the name
and value
pair your want. 您可以创建将由
form
解释的<custom-input>
自定义元素,只需在template
内添加一个隐藏的 input
元素,其中包含您想要的name
和value
对。
<template>
<input type="hidden" name="foo" value="defaultVal">
</template>
The default value
(and name
) can by updated by your custom element internal logic. 默认
value
(和name
)可以由您的自定义元素内部逻辑更新。
This hidden input
must not be inserted inside a Shadow DOM to be detected by the container form
. 此隐藏
input
不得插入Shadow DOM中以供容器form
检测。
(function() { var iconDoc = (document._currentScript || document.currentScript).ownerDocument; var objectPrototype = Object.create(HTMLInputElement.prototype); objectPrototype.createdCallback = function() { //var shadow = this.createShadowRoot(); var template = iconDoc.querySelector('#test'); this.appendChild(template.content.cloneNode(true)); }; document.registerElement('custom-input', { prototype: objectPrototype }); })(); console.log( $('form').serialize() )
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <template id="test"> <input type="hidden" name="foo" value="bar"> </template> <form> <input name="regular" value="input"> <custom-input name="foo" value="bar"></custom-input> </form>
You can do this: 你可以这样做:
(function() { var newInputExtended = Object.create(HTMLInputElement.prototype); newInputExtended.createdCallback = function() { this.value = 'baz'; }; document.registerElement('foo-input', { extends: 'input', prototype: newInputExtended }); window.something = function(form, event) { $('<p>') .text($(form).serialize()) .appendTo('body') event.preventDefault(); } })();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <form onsubmit="something(this, event)"> <input is="foo-input" name="foo" value="bar"> <button>Hi</button> </form>
But you get an error if you try to create a new shadow root. 但是如果您尝试创建新的影子根,则会出现错误。 It looks like you are limited to only extending the data/logic around the element's user-agent shadow root.
看起来您只能在元素的用户代理阴影根周围扩展数据/逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.