Я пытаюсь создать элемент управления, позволяющий пользователю устанавливать значение как с помощью числового ввода, так и с помощью ползунка. Прочитав соответствующие документы , вот с чем я пришел:
class NumberAndRange extends HTMLElement {
constructor() {
super()
const shadow = this.attachShadow({mode: 'open'})
this.number = document.createElement('input')
this.number.type = 'number'
this.range = document.createElement('input')
this.range.type = 'range'
this.number.addEventListener('input',
()=>{this.range.value = this.number.value}
)
this.range.addEventListener('input',
()=>{this.number.value = this.range.value}
)
shadow.appendChild(this.number)
shadow.appendChild(this.range)
}
}
customElements.define('number-and-range', NumberAndRange)
<number-and-range></number-and-range>
Как вы можете видеть, это работает (по крайней мере, в браузерах, которые поддерживают это). Для краткости я пропустил код, который гарантирует, что установка атрибутов min
, max
, step
и т. Д. На numeric-and-range
также устанавливает их на input
s, и что чтение этих атрибутов из numeric-and-range
возвращает значимое результаты.
Однако есть одна функция, которую я не могу добавить. Ясно, что мы хотели бы, чтобы запуск события input
на numeric
и range
также вызывал это событие на numeric-and-range
; так что мы можем забыть, что numeric-and-range
на самом деле состоит из двух входов и вместо этого рассматривать его, как если бы это был один элемент управления. Поэтому:
class NumberAndRange extends HTMLElement {
constructor() {
super()
const shadow = this.attachShadow({mode: 'open'})
this.number = document.createElement('input')
this.number.type = 'number'
this.range = document.createElement('input')
this.range.type = 'range'
this.number.addEventListener('input',
()=>{this.range.value = this.number.value}
)
this.range.addEventListener('input',
()=>{this.number.value = this.range.value}
)
const whole = this
this.number.addEventListener('input',
(ev)=>{whole.dispatchEvent(ev)}
)
this.range.addEventListener('input',
(ev)=>{whole.dispatchEvent(ev)}
)
shadow.appendChild(this.number)
shadow.appendChild(this.range)
}
}
customElements.define('number-and-range', NumberAndRange)
<number-and-range></number-and-range>
Но это не работает! По причинам, не зависящим от меня, движение слайдер бросает InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable
Какой объект нельзя использовать? И почему бы его не использовать? Я смотрю на свой код и не могу найти ошибку.
Не могли бы вы просветить меня, что я делаю не так?
Редактировать: Идея, предложенная в комментариях, мне тоже не подходит:
class NumberAndRange extends HTMLElement {
connectedCallback() {
const whole = this
this.number.addEventListener('input',
(ev)=>{whole.dispatchEvent(ev)}
)
this.range.addEventListener('input',
(ev)=>{whole.dispatchEvent(ev)}
)
}
constructor() {
super()
const shadow = this.attachShadow({mode: 'open'})
this.number = document.createElement('input')
this.number.type = 'numeric'
this.range = document.createElement('input')
this.range.type = 'range'
this.number.addEventListener('input',
()=>{this.range.value = this.number.value}
)
this.range.addEventListener('input',
()=>{this.number.value = this.range.value}
)
shadow.appendChild(this.number)
shadow.appendChild(this.range)
}
}
customElements.define('number-and-range', NumberAndRange)
<number-and-range></number-and-range>