'JavaScript function only works after page reload

I know this has been asked a lot on here, but all the answers work only with jQuery and I need a solution without it.

So after I do something, my Servlet leads me to a JSP page. My JS function should populate a drop down list when the page is loaded. It only works properly when the page is refreshed tho.

As I understand this is happening because I want to populate, using innerHTML and the JS function gets called faster then my HTML page.

I also get this error in my Browser:

Uncaught TypeError: Cannot read property 'innerHTML' of null
at XMLHttpRequest.xmlHttpRequest.onreadystatechange

I had a soulution for debugging but I can't leave it in there. What I did was, every time I opened that page I automatically refreshed the whole page. But my browser asked me every time if I wanted to do this. So that is not a solution that's pretty to say the least.

Is there something I could do to prevent this?

Edit:

    document.addEventListener("DOMContentLoaded", pupulateDropDown);
function pupulateDropDown() {
  var servletURL = "./KategorienHolen"
  let xmlHttpRequest = new XMLHttpRequest();

  xmlHttpRequest.onreadystatechange = function () {
    if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status === 200) {

      console.log(xmlHttpRequest.responseText);

      let katGetter = JSON.parse(xmlHttpRequest.responseText);
      JSON.stringify(katGetter);

        var i;
    for(i = 0; i <= katGetter.length -1; i++){
      
       
      console.log(katGetter[i].id);
      console.log(katGetter[i].kategorie);
      console.log(katGetter[i].oberkategorie);
    
       if (katGetter[i].oberkategorie === "B") {

        document.getElementById("BKat").innerHTML += "<a href=" + "DisplayKlamotten" + "?searchfor=" + katGetter[i].kategorie + ">" + katGetter[i].kategorie + "</a></br>";
      
      } else if (katGetter[i].oberkategorie === "S") {    
           
        document.getElementById("SKat").innerHTML += "<a href=" + "DisplayKlamotten" + "?searchfor=" + katGetter[i].kategorie + ">" + katGetter[i].kategorie + "</a></br>";

      } else if (katGetter[i].oberkategorie ==="A") {

        document.getElementById("ACat").innerHTML += "<a href=" + "DisplayKlamotten" + "?searchfor=" + katGetter[i].kategorie + ">" + katGetter[i].kategorie + "</a></br>";
      }


      // document.getElementsByClassName("innerDiv").innerHTML = "<a href=" + "DisplayKlamotten" + "?=" + katGetter.kategorie + ">" + katGetter.kategorie + "</a>";
      // document.getElementById("test123").innerHTML = "<a href=" + "DisplayKlamotten" + "?searchfor=" + katGetter.kategorie + ">" + katGetter.kategorie + "</a>";

    }



    }
  };
  xmlHttpRequest.open("GET", servletURL, true);
  xmlHttpRequest.send();
}


Solution 1:[1]

It can depend on how + when you're executing the code.

<html>
  <head>
  <title>In Head Not Working</title>
  <!-- WILL NOT WORK -->
  <!--<script>
     const p = document.querySelector('p');
     p.innerHTML = 'Replaced!';
  </script>-->
  </head>
  <body>
  <p>Replace This</p>
  <!-- Will work because the page has finished loading and this is the last thing to load on the page so it can find other elements -->
  <script>
     const p = document.querySelector('p');
     p.innerHTML = 'Replaced!';
  </script>
  </body>
</html>

Additionally you could add an Event handler so when the window is fully loaded, you can then find the DOM element.

<html>
  <head>
    <title>In Head Working</title>
    <script>
      window.addEventListener('load', function () {
        const p = document.querySelector('p');
        p.innerHTML = 'Replaced!';
      });
    </script>
  </head>
  <body>
    <p>Replace This</p>
  </body>
</html>

Solution 2:[2]

Define your function and add an onload event to body:

<body onload="pupulateDropDown()">
    <!-- ... -->
</body>

Solution 3:[3]

Script needs to be loaded again, I tried many options but <iframe/> works better in my case. You may try to npm import for library related to your script or you can use the following code.

<iframe
        srcDoc={`
          <!doctype html>
          <html>
            <head>
              <style>[Style (If you want to)]</style>
            </head>
            <body>
              <div>
                [Your data]
                <script type="text/javascript" src="[Script source]"></script>
              </div>
            </body>
          </html>
        `}
      />

Inside srcDoc, it's similar to normal HTML code.

You can load data by using ${[Your Data]} inside srcDoc.

Solution 4:[4]

It should work :

document.addEventListener("DOMContentLoaded", function(){
    //....
});

Solution 5:[5]

You should be using the DOMContentLoaded event to run your code only when the document has been completely loaded and all elements have been parsed.

window.addEventListener("DOMContentLoaded", function(){
   //your code here
});

Alternatively, place your script tag right before the ending body tag.

<body>
<!--body content...-->
<script>
//your code here
</script>
</body>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 codingwithmanny
Solution 2 Lajos Arpad
Solution 3 Jay Pokale
Solution 4 Kerem atam
Solution 5 Unmitigated