t2ym / i18n-element

I18N Base Element for Lit and Polymer
Other
9 stars 1 forks source link

[Tips] this.text is not for this element in a base class of an extended element #67

Open t2ym opened 5 years ago

t2ym commented 5 years ago

[Tips] this.text is not for this element in a base class of an extended element

Root Cause

In an extended element, this.text refers to the text property for the extended element, not for the base element. This is as designed.

How to get the proper text object of the base element in directives

class MyBaseElement extends i18n(HTMLElement) {
  constructor() { super(); this.items = ['item 1', 'item 2', 'item 3']; ... }
  render() {
    let binding = bind(this, 'my-base-element');
    let text = this.getText('my-base-element', import.meta);
    // text has not been initialized at the first rendering before preprocessing
    text = text.model ? text : null;
    return html`${'my-base-element', binding}
      ${text 
        ? repeat(this.items, i => i, i => html`<div>${text.header} ${i}</div>`)
        : nothing /* empty (or any value) at the first rendering */ }
      <template>
        <span id="header">Header</span>
      </template>`;
  }
}

Define an inner template to avoid the this identity issue

const innerBinding = bind('inner-template', import.meta);
class MyBaseElement extends i18n(HTMLElement) {
  constructor() { super(); this.items = ['item 1', 'item 2', 'item 3'];
    this.addEventListener('lang-updated', this.langUpdated);
    // 'lang-updated' event may come asynchronously after that for 'my-base-element'
    innerBinding.element.addEventListener('lang-updated', this.langUpdated.bind(this));
    ...
  }
  connectedCallback() { this.invalidate(); }
  langUpdated(event) { this.invalidate(); }
  render() {
    return html`${bind(this, 'my-base-element')}
      ${repeat(this.items, i => i, i => 
        html`${'inner-template', innerBinding}<div>Header ${i}</div>`)}`;
  }
  invalidate() { /* render */ ... }
}