Как я могу создать веб-компонент, который действует как элемент формы?

Я пытаюсь создать веб-компонент, который будет использоваться в элементе формы специально, который имеет name и value, Я понимаю, что могу создать веб-компонент, который extends HTMLInputElement:

<input is="very-extended">

но я пытаюсь создать совершенно новый элемент.

При создании обычного веб-компонента вы можете создать его из прототипа обычного веб-компонента. HTMLElement (HTMLElement.prototype). Что заставляет меня предположить, что я могу создать другой элемент с прототипом HTMLInputElement (HTMLInputElement.prototype). Вы на самом деле используете этот прототип, когда extending API элементов ввода, так почему я не могу использовать этот прототип для создания совершенно нового элемента, который работает в форме?

Если вы посмотрите на теневую область обычного поля ввода:

Вы можете видеть, что внутри есть div. Я понимаю что это HTMLInputElement имеет методы и атрибуты, методы получения / установки и т. д. Так почему же, когда я пытаюсь создать свой компонент, он не может быть частью имени, пары значений, найденные в форме?

Вот пример того, как я пытаюсь создать этот веб-компонент:

Обратите внимание, что его следует протестировать в браузере, поддерживающем веб-компоненты.

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

Почему имя, пара значений не найдены в форме, и как я могу создать пользовательский элемент формы?

3 ответа

Решение

Вы можете создать свой <custom-input> пользовательский элемент, который будет интерпретироваться form, просто добавив в свой template скрытый input элемент с name а также value сопряжение ваше желание.

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

По умолчанию value (а также name) может быть обновлен с помощью пользовательского элемента внутренней логики.

Это скрытое 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>

KevBot,

Вы, кажется, думаете, что элемент включает себя в форму. Это не относится к делу. Это форма, которая ищет свои дочерние элементы по имени тега, чтобы решить, какие элементы она должна включать. Он будет просто игнорировать тех, у кого неизвестные имена тегов.

Ваш custom-input имя не входит в число элементов, которые ищет форма. Таким образом, он не включен в форму. Не имеет значения прототип пользовательского элемента. Вот почему это работает, если вы используете is, с тех пор имя тега сохраняется.

Конечно, вы можете реализовать свой собственный custom-form который ведет себя по-другому, если хотите.

Вы можете сделать это:

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

Но вы получите ошибку, если попытаетесь создать новый теневой корень. Похоже, вы ограничены только расширением данных / логики вокруг теневого корня пользовательского агента элемента.

Другие вопросы по тегам