Создание настраиваемого поля ввода с веб-компонентами, добавляемыми через шаблон и настраиваемыми перед добавлением в DOM - PullRequest
0 голосов
/ 27 февраля 2019

Я пытаюсь создать пользовательское текстовое поле с помощью веб-компонентов

'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?Заданная процедура также срабатывает только один раз.

Ответы [ 2 ]

0 голосов
/ 29 марта 2019

Вам не нужно расширять 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)
с ними есть некоторые проблемы.
0 голосов
/ 13 марта 2019

Значение - это атрибут ввода, а не свойство.Чтобы установить атрибут элемента HTML, вы должны использовать textbox.setAttribute('value', myNewValue)

...