Создание настраиваемого поля ввода с веб-компонентами, добавляемыми через шаблон и настраиваемыми перед добавлением в DOM
Я пытаюсь создать собственное текстовое поле через веб-компоненты
'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.log("input can be validated");
}
get value() {
console.log("get");
let textbox = this.shadowRoot.querySelector("input");
return textbox.value;
}
set value(newValue) {
console.log("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? Заданная процедура также срабатывает только один раз.
0 ответов
Значение - это атрибут ввода, а не свойство. Чтобы установить атрибут элемента HTML, вы должны использовать textbox.setAttribute('value', myNewValue)
Вам не нужно расширять 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.log('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)