WebReflection / hyperHTML-Element

An extensible class to define hyperHTML based Custom Elements.
ISC License
202 stars 25 forks source link

How about support for ref attributes #51

Closed jfbrennan closed 5 years ago

jfbrennan commented 5 years ago

Several other libs support a ref attribute in template markup so those elements can easily be referenced as this.refs. This is handy and would be great to have in HyperHTMLElement. Right now I have to write this boilerplate for all my refs:

  connectedCallback() {
    // Boilerplate, make it go away please :)
    this.refs = {
      input: this.querySelector('[ref=input]'),
      results: this.querySelector('[ref=results]')
    };

    if (this.hasAttribute('autofocus')) this.refs.input.focus();
  }

// Inside render()
    this.html`
      <input ref="input" type="text">
      <ul ref="results">...</ul>`;
WebReflection commented 5 years ago

ref is not standard while this project is about sticking with standards as much as possible.

Regardless, ref=${hookRef} already landed in lighterhtml to be able to const hookRef = useRef(null) with generic hooks, provided by augmentor or other libraries.

It'd be weird to implement a different ref for hyperHTML, but it might be handy to think about an implementation that works in both cases.

Meanwhile, how about you extend the HyperHTMLElement base class with one that provides a lazy utility for you?

class HyperHTMLReferences extends HyperHTMLElement {
  get refs() {
    let {_refs} = this;
    if (!_refs) {
      _refs = {};
      for (let
        all = (this.shadowRoot || this).querySelectorAll('[ref]'),
        i = 0, {length} = all;
        i < length; i++
      ) {
        const node = all[i];
        const key = node.getAttribute('ref');
        if (key)
          _refs[key] = node;
      }
    }
    return _refs;
  }
}

In that case you have this.refs pointing at whatever you want in any subclass as long as you access it after rendering.

Would that work for the time being?

WebReflection commented 5 years ago

You know what? lighterhtml ref implementation for hooks would still work even with this change so I've made it possible to use refs with HyperHTMLElement, just remember it won't give you anything until you render at least once.

sourcegr commented 5 years ago

Nice one...

What if a ref becomes (un)available due to a condition that adds it to the dom under certain conditions?

WebReflection commented 5 years ago

it cannot become unavailable so that's not a concern or, if it is, you can keep doing whatever you were doing before ignoring this feature 👋

jfbrennan commented 5 years ago

@WebReflection this is great! Can I help with documenting this feature? I don't see it documented anywhere...

WebReflection commented 5 years ago

Can I help with documenting this feature?

yes please !