Я пытаюсь создать собственное текстовое поле с помощью веб-компонентов.
'use strict';
class TextBox extends HTMLElement {
constructor() {
super();
var shadow = this.attachShadow({ mode: 'open' });
let textbox = document.createElement("input");
shadow.appendChild(textbox);
textbox.addEventListener("change", this.validate);
textbox.value = "Init";
}
validate(event) {
console.info("input can be validated");
}
get value() {
console.info("get");
let textbox = this.shadowRoot.querySelector("input");
return textbox.value;
}
set value(newValue) {
console.info("set");
let textbox = this.shadowRoot.querySelector("input");
textbox.value = newValue;
}
}
customElements.define('test-textbox',TextBox);
Позже я хотел бы встроить пользовательский ввод в шаблон и изменить его значения перед его добавлением:
let control= document.getElementById("control");
let clone = control.content.cloneNode(true);
clone.children[0].value = "tb value has been changed before adding";
document.getElementById("app").appendChild(clone);
Но если сделать это в моем коде, значение ввода останется на «Init», но значение моего пользовательского элемента управления будет иметь свойство «значение tb было изменено перед добавлением».
Было бы лучше расширить HTMLInput? Установленная процедура также срабатывает только один раз.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Значение является атрибутом ввода, а не свойством. Чтобы установить атрибут элемента HTML, вы должны использовать textbox.setAttribute('value', myNewValue)
Разве ценность не является одновременно и свойством, и атрибутом?
не совсем -> stackoverflow.com/questions/6003819/…
Вам не нужно расширять HTMLInput. Вот как бы я это сделал. Я добавил все свойства, прикрепленные к <text-box />, к его внутреннему элементу ввода, но в этом нет необходимости, если только вы не пытаетесь более точно имитировать элемент ввода.
Я надеюсь, что расширение определенных элементов, таких как HTMLInput, не станет проблемой в ближайшее время, но я стараюсь избегать их, потому что с ними есть некоторые проблемы в момент.
const css = `
<style>
:host([hidden]) { display: none; }
:host {
display: block;
}
input {
background-color: #f5f5f5;
border: 1px solid transparent;
border-radius: 4px;
padding: 1em;
font-size: 16px;
width: 400px;
}
input:focus {
background-color: #fff;
border: 1px solid #dadce0;
outline: 0;
}
</style>
`
const html = `<input type='text' value='Init' />`
class TextBox extends HTMLElement {
static get observedAttributes () {
return ['value']
}
constructor () {
super()
this.attachShadow({mode: 'open'})
this.shadowRoot.appendChild(template.content.cloneNode(true))
// Cache the value of the inputNode
this.inputNode = this.shadowRoot.querySelector('input')
this.inputNode.value = 'Something else'
// Add all properties on text-box to input
for (let i = 0; i < this.attributes.length; i++) {
this.inputNode.setAttribute(
this.attributes[i].nodeName,
this.attributes[i].nodeValue
)
}
}
validate (event) {
console.info('input can be validated')
}
get value () {
return this.inputNode.value
}
set value (newValue) {
this.inputNode.value = newValue
}
connectedCallback () {
this.inputNode.addEventListener('change', this.validate)
}
disconnectedCallback () {
this.inputNode.removeEventListener('change', this.validate)
}
attributeChangedCallback (name, oldValue, newValue) {
if (name === 'value') {
this.inputNode.value = newValue
}
}
}
const template = document.createElement('template')
template.innerHTML = `${css}${html}`
window.customElements.define('text-box', TextBox)
См. сообщение для пользовательского элемента с вводом внутри него stackoverflow.com/a/40173805/4600982