2

I'm trying to recreate a simple program of mine using lit instead of just basic js, but adding import statements seems to break every function.

Things seem to work just fine with "type": "module" alone in my package.json, but the second I change type="text/javascript" to type="module" in my script link within my html, or when I add:

import {LitElement, html} from 'lit';
import {customElement, property} from 'lit/decorators.js';

to the top of my app.js, or even both in combination, none of my functions seem to work anymore.

I tried changing the scope of my functions as suggested in this thread: Functions not working when ```type="module"``` or import , but that didn't seem to have any effect.

Here is an example of one such function:

function initialize()
{
    xWins = window.sessionStorage.getItem('xWins');
    oWins = window.sessionStorage.getItem('oWins');
    draws = window.sessionStorage.getItem('draws');
    if(xWins == null) { xWins = 0; }
    if(oWins == null) { oWins = 0; }
    if(draws == null) { draws = 0; }
    document.getElementById('numXWins').innerHTML = "X WINS: " +xWins;
    document.getElementById('numOWins').innerHTML = "O WINS: " +oWins;
    document.getElementById('numDraws').innerHTML = "DRAWS: " +draws;
}

Is there something I'm missing? How can I keep my functions working after I add import statements?

EDIT: Added my index.html for completion's sake

<!DOCTYPE html>
<head>
    <link rel="stylesheet" href="style.css">
    <script type="text/javascript" src="./app.js" defer></script>
    <script src="https://unpkg.com/mathjs/lib/browser/math.js"></script>
</head> 
<body onload="initialize();">
    <h3>Tic Tac Toe</h3>
    <p id="rules">Rules: One player chooses X's, the other chooses O's. Take turns drawing your symbols onto a square. The first to get three in a row wins!</p>    
    <table id="scoreboard">
        <thead>
            <tr>
                <td id="numXWins">X WINS</td>
                <td id="numOWins">O WINS</td>
                <td id="numDraws">DRAWS</td>
            </tr>
        </thead>
        <tbody>
            <td>0</td>
            <td>0</td>
            <td>0</td>
        </tbody>
    </table>
    <br>
    <table id="gameboard">
        <tr>
            <td><input type="button" name="gamecell" value="   " class="0,0" onclick="play(this);"></td>
            <td><input type="button" name="gamecell" value="   " class="0,1" onclick="play(this);"></td>
            <td><input type="button" name="gamecell" value="   " class="0,2" onclick="play(this);"></td>
        </tr>
        <tr>
            <td><input type="button" name="gamecell" value="   " class="1,0" onclick="play(this);"></td>
            <td><input type="button" name="gamecell" value="   " class="1,1" onclick="play(this);"></td>
            <td><input type="button" name="gamecell" value="   " class="1,2" onclick="play(this);"></td>
        </tr>
        <tr>
            <td><input type="button" name="gamecell" value="   " class="2,0" onclick="play(this);"></td>
            <td><input type="button" name="gamecell" value="   " class="2,1" onclick="play(this);"></td>
            <td><input type="button" name="gamecell" value="   " class="2,2" onclick="play(this);"></td>
        </tr>
    </table>
    <p id="caption" value="Current Turn: X">Current Turn: X</p>
    <input type="button" id="rematch" value="Rematch?" onclick="rematch();">
</body>
</html>
Cameron Crane
  • 113
  • 1
  • 12
  • 1
    How are you loading your js? Show your index.html – Christian Apr 22 '22 at 05:48
  • @Christian Just added it! I also tried loading it as ```type="module"``` and had no luck. – Cameron Crane Apr 22 '22 at 14:32
  • 1
    What's that template in your html? Try to put everything into an element. The decorators suggest you are using typescript? Can you create an example with all the methods? – Christian Apr 23 '22 at 09:16
  • My mistake, the template was from something I was testing but forgot to remove before posting it here. And this should be pure javascript, not typescript. Also sorry if this is a dumb question, but how would I create an example? I can also summarize them here if you'd like, but they seem to work perfectly on their own without the import statements at the top, so I'm not sure they're the issue. – Cameron Crane Apr 25 '22 at 15:27
  • Bad thing here on stackoverflow is, that modules are not supported. So either the cumbersome way as below or you go over at codesandbox. – Christian Apr 25 '22 at 15:46

1 Answers1

1

The best thing you can do is that everything is an element, like for example in the snippet below.

<script type="module">
import {
  LitElement,
} from "https://unpkg.com/lit-element/lit-element.js?module";
import {html} from "https://unpkg.com/lit/static-html.js?module";

class MyElement extends LitElement {
  
  constructor() {
    super();
  }
  
  play(e) {
    console.log('play');
    e.target.value = 'X';
  }
  
  rematch() {
    console.log('rematch');
  }
  
  render() {
    return html`
      <h3>Tic Tac Toe</h3>
    <p id="rules">Rules: One player chooses X's, the other chooses O's. Take turns drawing your symbols onto a square. The first to get three in a row wins!</p>    
    <table id="scoreboard">
        <thead>
            <tr>
                <td id="numXWins">X WINS</td>
                <td id="numOWins">O WINS</td>
                <td id="numDraws">DRAWS</td>
            </tr>
        </thead>
        <tbody>
            <td>0</td>
            <td>0</td>
            <td>0</td>
        </tbody>
    </table>
    <br>
    <table id="gameboard">
        <tr>
            <td><input type="button" name="gamecell" value="   " class="0,0" @click="${this.play}"></td>
            <td><input type="button" name="gamecell" value="   " class="0,1" @click="${this.play}"></td>
            <td><input type="button" name="gamecell" value="   " class="0,2" @click="${this.play}"></td>
        </tr>
        <tr>
            <td><input type="button" name="gamecell" value="   " class="1,0" @click="${this.play}"></td>
            <td><input type="button" name="gamecell" value="   " class="1,1" @click="${this.play}"></td>
            <td><input type="button" name="gamecell" value="   " class="1,2" @click="${this.play}"></td>
        </tr>
        <tr>
            <td><input type="button" name="gamecell" value="   " class="2,0" @click="${this.play}"></td>
            <td><input type="button" name="gamecell" value="   " class="2,1" @click="${this.play}"></td>
            <td><input type="button" name="gamecell" value="   " class="2,2" @click="${this.play}"></td>
        </tr>
    </table>
    <p id="caption" value="Current Turn: X">Current Turn: X</p>
    <input type="button" id="rematch" value="Rematch?" @click="${this.rematch}">`
  }
}

customElements.define("my-element", MyElement);
</script>
<my-element></my-element>
Christian
  • 3,503
  • 1
  • 26
  • 47
  • This seems to cause the functions to work again, but my CSS is no longer attached to the elements within render(). (I reattached my css file and global changes seem to stay the same, i.e. the background image of the whole page, but the styling for individual elements is gone). How would I do this while allowing my css styling to remain? – Cameron Crane Apr 25 '22 at 15:29
  • Also: Why would I need to rewrite everything using lit just by importing it at the top? Does importing lit cause normal js/html to stop working correctly, thus making it necessary to rewrite everything in the lit format? – Cameron Crane Apr 25 '22 at 15:30
  • 1
    The css should be imported by using the css functions (get styles). This is because css in webcomponents apply only to the shadow dom, thus it is sandboxed (big advantage here). But you can override them. see my answer here https://stackoverflow.com/questions/70758391/implement-bootstrap-in-lit-element-with-javascript/70767978#70767978 – Christian Apr 25 '22 at 15:43
  • 1
    Regarding your second question, I think is more regarded to modules and how they are encapsulated rather than lit which is as far as I am aware only avail as module. – Christian Apr 25 '22 at 15:44