使用添加到模板的Web组件创建自定义输入字段,可通过模板添加和配置,然后添加到DOM

时间:2019-02-27 09:13:11

标签: javascript web-component native-web-component

我尝试通过Web组件创建自定义文本框

'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 :(得分:0)

值是输入的属性,而不是属性。要设置HTML元素的属性,您必须使用textbox.setAttribute('value', myNewValue)

答案 1 :(得分:0)

您不需要扩展HTMLInput。这就是我要做的。我将传递给<text-box />的所有属性添加到其内部输入元素中,但是除非您试图更紧密地模仿输入元素,否则没有必要。

我希望扩展像HTMLInput这样的特定元素不会很快成为问题,但是我倾向于避免使用它们,因为moment上存在一些问题。

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)