Создание настраиваемого поля ввода с веб-компонентами, добавляемыми через шаблон и настраиваемыми перед добавлением в 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.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? Установленная процедура также срабатывает только один раз.

См. сообщение для пользовательского элемента с вводом внутри него stackoverflow.com/a/40173805/4600982

Supersharp 28.02.2019 21:36
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
1 458
2

Ответы 2

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

Разве ценность не является одновременно и свойством, и атрибутом?

J. Doe 13.03.2019 15:19

не совсем -> stackoverflow.com/questions/6003819/…

Pascal L. 13.03.2019 23:04

Вам не нужно расширять 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)

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