What is the best way to wire global data in multiple places using hyperHTML?

140 Views Asked by At

I'm working on an application that reuses a lot of constants. I know that I can use wire IDs to use the same data in multiple places, but I'm not sure if I'm supposed to create a new globally unique ID every time I want to use that data.

This is a simplified example of what I'm working with:

const colors = [
  {value: 'red', label: 'Red'},
  {value: 'blue', label: 'Blue'}
]

class MyElement extends HTMLElement {
  constructor() {
    super()
    this.html = hyperHTML.bind(this)
  }

  connectedCallback() {
    this.html`
      Hi, ${this.getAttribute('name')}! What is your favorite color?<br/>
      <select>
        ${colors.map(option => hyperHTML.wire(option)`<option value=${option.value}>${option.label}</option>`)}
      </select>
    `
  }

  get name() {
    return this.getAttribute('name')
  }
}

customElements.define('my-element',MyElement);

hyperHTML.bind(document.body)`
  <my-element name="Alice"></my-element>
  <my-element name="Bob"></my-element>`

I know that unless I specify a wire ID, the options will only appear in one place. I could use :${this.name} as the wire ID, but I have to figure out what to do if there are two people with the same name, and if I want to have one form for "What is your favorite color?" and another for "What color is your shirt?", I have to make another unique ID for that.

Is there a way to somehow scope wire IDs or do I have to make globally unique ones?

1

There are 1 best solutions below

1
On BEST ANSWER

There is a subtle issue in your logic, you'd like to map an array of items to themselves, instead of contextualizing their value.

Example: you are wiring the option object, out of usage, situation, context, instead of wiring the Custom Element instance to some data it's using to render itself.

As you can see in this CodePen example, you can simply wire the Custom Element context, and make the option information unique, in terms of scoped id, simply pointing at its value, through its owner:

hyperHTML.wire(this, `:option:${option.value}`)

At this point you'll have a single option element per each node so that you can easily select anything you want instead of moving the same option node globally all over the place.

Actually, the global ID is an anti-pattern as it is, I believe, in every other keyed framework such React or Vue so ... just use the instance, as your wire context/reference, and create a unique id for it with ease.

I hope this solved your issue.