WebReflection / hyperHTML

A Fast & Light Virtual DOM Alternative
ISC License
3.07k stars 112 forks source link

wire does not render when large number (50) components on page #215

Closed robhicks closed 6 years ago

robhicks commented 6 years ago

I have a web component that is repeated a number of times (possibly up to 100).

Each component gets a list of options for a select. The select looks like this:

<div id="controlledVocabulary-wrapper" class="${this.field.authorityList.listType === 'controlledVocabulary' ? '' : 'hidden'}">
  <div id="left"></div>
    <div id="right">
      <div id="cv-wrapper">
        <label for="cv-type">${this.t('controlled_vocabulary') || ''}</label>
         <select id="cv-type" name="cv-type" value="${this.field.authorityList.uri}" onchange="${this}">
                <option value="" default>${this.t('cv_select_type')}</option>
                ${cvList.map(li => {
                  let option = wire(li)`<option value="${li.uri}" selected="${this.field.authorityList.uri === li.uri ? true : null}">${li.en.displayName}</option>`;
                  // console.log('option', option);
                  return option;
                })}
      </select>
    </div>
  </div>
</div>

I can verify that the options are available through the option console.log. And the return statement returns the option elements. Nevertheless, the option elements never never get inserted into the DOM.

<select id="cv-type" name="cv-type">
  <option value="" default="">Select<!--_hyper: 1388970966;--></option>
   <!--_hyper: 1388970966;-->
</select>

The options render fine when the number of components is smaller (less than 5).

Any ideas why?

pinguxx commented 6 years ago

i try it here: https://codepen.io/pinguxx/pen/VXbPVB?editors=0010

seems to work, can you reproduce your problem in that pen?

robhicks commented 6 years ago

I can reproduce it here: https://codepen.io/robhicks/pen/GxmmRj?editors=1111

pinguxx commented 6 years ago

ah since you are passing the same object again and again to the wire, its just reusing the options elements again and again, if you give the employeelist a particular id and pass that to the wire, then that will create new option elements each time, or just dont pass li to wire and that will also do it wire(li, ':id' + this.someuniqueattr)`...` or just wire()`...`

WebReflection commented 6 years ago

@robhicks I think @pinguxx is right, if you use same weak reference wire will give you always the same resulting node. The :id part of the signature might help but in your very specific case, the cache is your issue: no matter how many options you create, the resulting node is always one related to that entry in the cache list.

You have two solutions, accordingly to your needs:

Unrelated

I've noticed that you use i18n via this.t('controlled_vocabulary'). I'd like to remind you that with hyperHTML you can define intents.

hyperHTML.define('i18n', (id) => {
  return i18n.t(id) || '';
});

Once you've done that upfront, at application level, you can write templates like this:

<div
  id="controlledVocabulary-wrapper"
  class="${this.field.authorityList.listType === 'controlledVocabulary' ? '' : 'hidden'}"
>
  <div id="left"></div>
    <div id="right">
      <div id="cv-wrapper">
        <label for="cv-type">${{i18n: 'controlled_vocabulary'}}</label>
         <select id="cv-type" name="cv-type" value="${this.field.authorityList.uri}" onchange="${this}">
          <option value="" default>${{i18n:'cv_select_type'}}</option>
            ${cvList.map((li, i) => wire(this, ':option-' + i)`
            <option value="${li.uri}" selected="${this.field.authorityList.uri === li.uri ? true : null}">
              ${li.en.displayName}
            </option>`)}
      </select>
    </div>
  </div>
</div>

edit this assuming you have a centralized i18n object instead of entries per each component, of course.

robhicks commented 6 years ago

@pinguxx Thanks!

robhicks commented 6 years ago

@WebReflection Thanks Andrea. Your explanation really helps. BTW, I'm just getting my feet wet with hyperHTML. A couple of us in our organization are trying to champion it's use. Currently, we're a big Polymer shop. Some of us are trying to break that trend and go native. Hopefully, that way we won't have to pinch our noses and use lit-html.

WebReflection commented 6 years ago

@robhicks happy to help doing that. Just in case, remember there is hyper.Component to help CustomElements-less projects, and HyperHTMLElement to help with Custom Elements projects 😉