Web Component with a Responsive Attribute

The content of the component changes when an attribute changes

by Erik Gillespie

HTML

<radio-input name="web-lang" value="html" label="HTML"></radio-input>
<radio-input name="web-lang" value="css" label="CSS"></radio-input>
<radio-input name="web-lang" value="js" label="JavaScript"></radio-input>

CSS

body {
  background-color: #222;
  color: white;
}

JavaScript

class RadioInput extends HTMLElement {
  constructor () {
    super()
    const name = this.getAttribute('name') || ''
    const value = this.getAttribute('value') || ''
    const label = this.getAttribute('label') || ''
    const id = value.toLowerCase().replace(/\s+/g, '-')
    this.innerHTML = `
      <div>
        <input id="${id}" type="radio" name="${name}" value="${value}">
        <label for="${id}">${label}</label>
      </div>
    `
  }
  
  static get observedAttributes () {
    return ['name', 'value', 'label']
  }

  attributeChangedCallback (name, oldValue, newValue) {
    if (name === 'name') {
      this.querySelector('input').setAttribute('name', newValue || '')
    } else if (name === 'value') {
      const value = newValue || ''
      const id = value.toLowerCase().replace(/\s+/g, '-')
      const input = this.querySelector('input')
      input.setAttribute('value', value)
      input.setAttribute('id', id)
      this.querySelector('label').setAttribute('for', id)
    } else if (name === 'label') {
      this.querySelector('label').textContent = newValue || ''
    }
  }
}

customElements.define('radio-input', RadioInput)