最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I create a web component that acts like a form element? - Stack Overflow

programmeradmin1浏览0评论

I am trying to create a web ponent that is usable in a form element specifically, that has a name, and a value. I recognize that I can create a web ponent that extendsan HTMLInputElement:

<input is="very-extended">

but I am trying to create an entirely new element.

When creating a regular web ponent, you can create it from the prototype of a regular HTMLElement (HTMLElement.prototype). Which leads me to assume that I can create a different element with the prototype of an 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?

If you look at the shadow dom of a regular input field:

you can see that there is a div inside of there. I understand that this HTMLInputElement has methods and attributes, getters/setters, etc. So why is it that when I attempt to create my ponent, it fails to be part of the name, value pairs found in the form?

Here is an example of how I am trying to create this web ponent:

Please note that his should be tested in a browser that supports web ponents.

(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=".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>

I am trying to create a web ponent that is usable in a form element specifically, that has a name, and a value. I recognize that I can create a web ponent that extendsan HTMLInputElement:

<input is="very-extended">

but I am trying to create an entirely new element.

When creating a regular web ponent, you can create it from the prototype of a regular HTMLElement (HTMLElement.prototype). Which leads me to assume that I can create a different element with the prototype of an 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?

If you look at the shadow dom of a regular input field:

you can see that there is a div inside of there. I understand that this HTMLInputElement has methods and attributes, getters/setters, etc. So why is it that when I attempt to create my ponent, it fails to be part of the name, value pairs found in the form?

Here is an example of how I am trying to create this web ponent:

Please note that his should be tested in a browser that supports web ponents.

(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./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?

Share Improve this question edited Dec 12, 2016 at 23:02 Supersharp 31.2k11 gold badges101 silver badges147 bronze badges asked Jul 27, 2016 at 21:05 KevBotKevBot 18.9k5 gold badges54 silver badges70 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

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.

<template>
    <input type="hidden" name="foo" value="defaultVal">
</template>

The default value (and name) can by updated by your custom element internal logic.

This hidden input must not be inserted inside a Shadow DOM to be detected by the container 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./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>

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. 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.

Of course, you may implement your own custom-form that behaves differently, if you want.

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./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.

发布评论

评论列表(0)

  1. 暂无评论