0

I need to have an external class comprising of game logic call a LitElement component, and pass it a html template literal which the component will use to update a portion of its own html template literal.

In the code below you will see a method of the component (navigationRender) which can be successfully called from within the component. That same method can also successfully be called from the external game class (as illustrated by the console.log). But, even though it can be called, it is not successfully updating the html template of the component.

Does navigationRender need some kind of callback into the scope of firstUpdated? I'm over my head here, and if that is what is needed, then I don't know how to do it anyhow ...

Below is code which has been condensed into a single file. If you click the "Change Description" button, then you will see the console.log update with the html template that was passed, but not the rendered html text.

<body>
  <front-end></front-end>
</body>

<script type="module">
  import { LitElement, html, css } from 'https://unpkg.com/lit-element?module';
  
  class FrontEnd extends LitElement {
    constructor() {
    super();
    this.renderDescription = html`<p>initialized - 01</p>`;
    }
    render() { 
      return [
        html`<button id="btn">Change Description</button>`,
        this.renderDescription]; 
    }
    firstUpdated() {
      this.game = new Game();
      this.navigationRender(html`<p>DESCRIPTION: So far, working when called from firstUpdated(). But what about when called from the Game class?</p>`);
      this.shadowRoot.getElementById('btn').addEventListener('click', (e) => {
        this.game.newDescription();
      });
    }
    navigationRender(description) {
      console.log(description);
      this.renderDescription = description;
      this.requestUpdate();
    }
  }
  customElements.define('front-end', FrontEnd);
  
  class Game {
    constructor() {
      this.frontEnd = new FrontEnd();
    }
    newDescription() {
      this.frontEnd.navigationRender(html`DESCRIPTION: Although the console.log verifies that this.frontEnd.navigationRender is being called and the data passed, that function is not able to actually update the this.renderDescription when called from the game class.`);
    }
  }
</script>

Thank you for your help and suggestions!

eadgbe
  • 93
  • 2
  • 9

1 Answers1

1

I figured it out. Hopefully, this will help someone else.

<body>
  <front-end id="fe-id"></front-end>
</body>

<script type="module">
  import { LitElement, html, css } from 'https://unpkg.com/lit-element?module';
  
  class FrontEnd extends LitElement {
    constructor() {
    super();
    this.renderDescription = html`<p>initialized - 01</p>`;
    }
    render() { 
      return [
        html`<button id="btn">Change Description</button>`,
        this.renderDescription]; 
    }
    firstUpdated() {
      this.game = new Game();
      this.navigationRender(html`<p>So far, working when called from firstUpdated(). But what about when called from the Game class?</p>`);
      this.shadowRoot.getElementById('btn').addEventListener('click', (e) => {
        this.game.newDescription();
      });
    }
    navigationRender(description) {
      console.log(description);
      this.renderDescription = description;
      this.requestUpdate();
    }
  }
  customElements.define('front-end', FrontEnd);
  
  class Game {
    constructor() {
      // this.frontEnd = new FrontEnd();
      this.element = document.getElementById('fe-id');
    }
    newDescription() {
      this.element.navigationRender(html`<p>YAY!!  THIS WORKS!!!</p>`);
    }
  }
</script>
eadgbe
  • 93
  • 2
  • 9
  • If you wanted to solve this in a more OOP style (and since Game doesn't need to know about the DOM layer yet), it would likely be enough to pass Frontend as a constructor argument for Game. Like this: `this.game = new Game(this);`. `this` is the instance of Frontend. Inside Game's constructor `this.frontEnd = frontend` The reason your first code failed was because you created a new instance of Frontend inside of Game (not a component, just a class instance) which isn't the same one that is created on page load by your markup. – Milton Apr 28 '20 at 22:22