0

My JS code looks like this. But when I open the page it says "Uncaught TypeError: Cannot set property 'innerHTML' of null"

I tried to change the NewItem constructor to a function. But VSC keeps saying I should declare it as a class instead. I converted it in the first place because the constructor wasn't working as a function either.

class NewItem {
    constructor(name, date, price) {
        this.itemName = name;
        this.itemDate = date;
        this.itemPrice = price;
    }
}


const onListItem = new NewItem("John", "Date", "Price");

document.getElementById("demo").innerHTML = onListItem.itemDate;

HTML looks like this

<!DOCTYPE html>
<html lang= "en">
    <head>
     <link rel="stylesheet" href="ShopListStyle.css">
     <meta name="viewport" content="width=device-width" initial-scale=1.0>   
     <title>Shopping List</title>   
    </head>
    <body>
        <script src="ShopListScript.js"></script>
        <div id="container">
            
            <div id="inputbox" class="section">
                <form id="labels-form">
                    <label><h2>Shopping List</h2></label>
                    <input id="labels-name" class="labels-input" type="text" value="Item Name"></input>
                    <input id="labels-date" class="labels-input" type="text" value="Date of Purchase"></input>
                    <input id="labels-price" class="labels-input" type="text" value="Item Price"></input>
                    <button id="labels-button">Add to List</button>
                    <p id="demo"></p>
                </form>
            </div>
            <div id="shopListBox" class="section">
                
                    <!--Need to add a delete button/ Maybe a quantity button down the road-->
                   <table id="shopList">
                    
                        <caption><h2>Spending List</h2></caption> 
                        <thead id="table-header">   
                            <tr>
                            <th class="table-header" id="table-name">name</th>
                            <th class="table-header" id="table-date">date</th>
                            <th class="table-header"id="table-price">price</th>
                            <th class="table-header" id="table-delete">delete</th>
                            </tr>
                        </thead>
                        <tbody id="table-body">
                            <tr class="newRow">
                                <td class="new-item" id="item-name">item</td>
                                <td class="new-item" id="item-date">item</td>
                                <td class="new-item" id="item-price">item</td>
                                <td class="new-item"><button class="item-button">Delete</button></td>
                            </tr>
                        </tbody>
                        <tfoot id="table-footer">
                            <tr>
                                <td id="item-price-sum" colspan="4" style="width: 100%" >Sum of Prices</td>
                            </tr>
                        </tfoot>
                   </table>
                   
                    <!--The sum of all the prices will go somewhere here-->
            </div>
        </div>
    </body>
</html>
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
Bl1xvan
  • 35
  • 8
  • What is your HTML? Do you have something with ID "demo"? When does this code run - does it run before the HTML is completely rendered? – VLAZ Jun 22 '21 at 14:13
  • Can you check if `document.getElementById("demo")` is not null? – Olaf Jun 22 '21 at 14:13
  • I just added the HTML the "demo" element is the "p" element under "Shopping List" – Bl1xvan Jun 22 '21 at 14:15
  • yeah, if you change your last line to `alert(onListItem.itemDate)`, it works perfect, so problem is that it just can't find your element with "demo" id. – Xth Jun 22 '21 at 14:15
  • How do I check demo is not null? – Bl1xvan Jun 22 '21 at 14:19
  • 1
    Honestly i don't understand where is the problem here, because i just copypasted your HTML and JS in the sandbox, and it works fine without any errors. https://jsfiddle.net/kr2z05e8/ – Xth Jun 22 '21 at 14:23
  • Where are you calling your JS? – disinfor Jun 22 '21 at 14:25
  • I just put the JS under the 'body' element, but it's still not working – Bl1xvan Jun 22 '21 at 14:29
  • What does "under the body" mean? After the opening `` or somewhere else? – disinfor Jun 22 '21 at 14:30
  • After the opening body tag. – Bl1xvan Jun 22 '21 at 14:32
  • Put this inside document onload, it will help you. Or put script at end of body tag. – Tushar Shahi Jun 22 '21 at 14:32
  • @Bl1xvan that's most likely your issue, since the javascript is running before the element exists in the DOM. Put it right before the closing `

    ` tag and test it.

    – disinfor Jun 22 '21 at 14:34
  • 1
    Does this answer your question? [Why does jQuery or a DOM method such as getElementById not find the element?](https://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element) – disinfor Jun 22 '21 at 14:35
  • I'm calling JS right above the closing body tag now. Like this `

    ` The JS seems to be working now. But onListItem.date is coming up as "undefined" on the page

    – Bl1xvan Jun 22 '21 at 14:36

2 Answers2

2

Your JavaScript code is trying to access this element with id demo (<p id="demo"></p>):
document.getElementById("demo").innerHTML = onListItem.itemDate;

Your script is added at the opening body tag...

    <body>
        <script src="ShopListScript.js"></script>
        ...

...which means the demo element does not exist yet.

Solution: Put your script before the closing body tag:

        ...
        <script src="ShopListScript.js"></script>
    </body>
</html>
Peter Krebs
  • 3,831
  • 2
  • 15
  • 29
0

You can also try to set

<script src="ShopListScript.js" defer="defer"></script>

Because javascript will block the DOM rendering, so we should put in the end of

like Peter Krebs's answer:

        ...
    <script src="ShopListScript.js"></script>
</body>
Smallnine
  • 165
  • 7