53

I'm getting the following error

Uncaught TypeError: Cannot read property 'appendChild' of null

myRequest.onreadystatechange @ script.js:20

with my following code

// index.html <html> <head> <title>Simple Page</title> </head> <body> <div id="mainContent"> <h1>This is an AJAX Example</h1> </div> <script type="text/javascript" src="script.js"></script> </body> </html> 

And here is my JavaScript file

// script.js // 1. Create the request var myRequest; // feature check! if(window.XMLHttpRequest) { // Firefox, Safari myRequest = new XMLHttpRequest(); } else if (window.ActiveXObject){ // IE myRequest = new ActiveXObject("Microsoft.XMLHTTP"); } // 2. Create an event handler for our request to call back myRequest.onreadystatechange = function() { console.log("We were called!"); console.log(myRequest.readyState); if(myRequest.readyState === 4){ var p = document.createElement("p"); var t = document.createTextNode(myRequest.responseText); p.appendChild(t); document.getElementById("mainContent").appendChild(p); } }; // 3. open and send it myRequest.open("GET","simple.txt", true); // any parameters? myRequest.send(null); 

And here is the contents of simple.txt

This is the contents of a simple text file.

I put the script tag at the bottom of the html as suggested by @Tejs here but I'm still getting this error.

2
  • It does not display the contents of simple.txt below my h1 tag. Plus I get the error in the console Commented May 3, 2015 at 13:11
  • You were right. I had a mix up with my files. It's working now. Thanks Commented May 3, 2015 at 13:23

13 Answers 13

96

For people who have the same issue of querySelector or getElementById that returns the following error:

Uncaught TypeError: Cannot read property 'appendChild' of null 

but you have a class name or id in the HTML...

If your script tag is in the head, the JavaScript is loaded before your HTML, therefore the element you are trying to access does not exist in the DOM yet. You will need to add defer to your script like so:

<script src="script.js" defer></script> 
Sign up to request clarification or add additional context in comments.

3 Comments

adding defer will make your code browser dependent. check my answer given below. sifr_dot_in
Putting "defer" in the script file solves the problem. With "defer" the javascript file is opened last on the page. Thus, it prevents the error from occurring.
Omg, thank you I was starting to lose my mind. The script tag was in the body, but it somehow ended up above the element I was trying to manipulate.
28

There isn't an element on your page with the id "mainContent" when your callback is being executed.

In the line:

document.getElementById("mainContent").appendChild(p); 

the section document.getElementById("mainContent") is returning null

3 Comments

I have an id called mainContent in my html. I'm I missing something?
5 years later @Sparky do you want to show your code regarding the prop error appendchild?
@Timo I don't think he does
14

Nice answers here. I encountered the same problem, but I tried <script src="script.js" defer></script> but I didn't work quite well. I had all the code and links set up fine. The problem is I had put the js file link in the head of the page, so it was loaded before the DOM was loaded. There are 2 solutions to this.

  1. Use
window.onload = () => { //write your code here } 
  1. Add the <script src="script.js"></script> to the bottom of the html file so that it loads last.

Comments

6

those getting querySelector or getElementById that returns the following error:

Uncaught TypeError: Cannot read property 'appendChild' of null 

or any other property, even if you have a class name or id in the HTML

don't use (defer as it is too much browser dependent.)

<script src="script.js" defer></script> //don't use this 

instead, put all your code in 'script.js' inside

$(document).ready(function(){ //your script here. } 

3 Comments

Isn't this just moving the dependency from "cross browser" to "jQuery" ? Perhaps add a POJS version.
The OP doesn't specify that they're using jQuery
The equivalent to the jquery version is stackoverflow.com/a/21814964/1906168
4

Instead of using your script tag defining the source of your .js file in <head>, place it at the bottom of your HTML code.

Comments

2

Had the same problem when Load external without cache using Javascript

Load external <script> without cache using Javascript

Had a good solution for cache problem here:

https://www.c-sharpcorner.com/article/how-to-force-the-browser-to-reload-cached-js-css-files-to-reflect-latest-chan/

But this happend: Uncaught TypeError: Cannot read property 'appendChild' of null.

Here is good explanation: https://stackoverflow.com/a/58824439/14491024

As it said your script tag is in the head, the JavaScript is loaded before your HTML.

Error

In Visual Studio by C# this problem is solved like this by adding Guid:

Guid

Here is how it looks in the View page source:

OK

Comments

2

Had this thing with REACT. Y just have to use try/catch or just if(elem !=null) to prevent React from crashing as it makes pre-rerenders for VirtualDom before any DOM is created!)

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
2

The "Cannot read property 'appendChild' of null" error occurs for 2 reasons:

  • Calling the appendChild() method on a DOM element that doesn't exist.

  • Insert the JS script tag above the HTML, where the DOM elements are declared.

Your issue is caused by the second error. You can solve it by moving and editing your JS script tag from the body tag into the head tag. For example:

// index.html <html> <head> <title>Simple Page</title> <script async defer src="script.js"></script> </head> <body> <div id="mainContent"> <h1>This is an AJAX Example</h1> </div> </body> </html> 

Comments

1

If this is happening to you in an AJAX post, you'll want to compare the values that you're sending and the values that the Controller is expecting.

In my case, I had changed a parameter in a serializable class from State to StateID, and then in an AJAX call didn't change the receiving field out 'data'

success: function (data) { MakeAddressForm.formData.StateID = data.State;

Note that the class was changed - it doesn't matter what I call it in the formData.

This created a null reference in the formData which I was trying to post back to the Controller once I'd done the update. Obviously, if someone changed the state (which was the purpose of the form) then they didn't get the error, so it made for a hard one to find.

This also through a 500 error. I'm posting this here in hopes it saves someone else the time I've wasted

Comments

1

put your javascript at the bottom of the page (ie after the element getting defined..)

Comments

1

add your script tag on the bottom of the body tag. so that script loads after html content then you won't get such error and add=

1 Comment

Please try to give an explanation with the pseudo-code so that the future audience gets what you are trying to convey.
0

Use querySelector insted of getElementById();

var c = document.querySelector('#mainContent'); c.appendChild(document.createElement('div')); 

Comments

-2

You can load your External JS files in Angular and you can load them directly instead of defining in index.html file.

component.ts:

ngOnInit() { this.loadScripts(); } loadScripts() { const dynamicScripts = [ //scripts to be loaded "assets/lib/js/hand-1.3.8.js", "assets/lib/js/modernizr.jr.js", "assets/lib/js/jquery-2.2.3.js", "assets/lib/js/jquery-migrate-1.4.1.js", "assets/js/jr.utils.js" ]; for (let i = 0; i < dynamicScripts.length; i++) { const node = document.createElement('script'); node.src = dynamicScripts[i]; node.type = 'text/javascript'; node.async = false; document.getElementById('scripts').appendChild(node); } } 

component.html:

<div id="scripts"> </div> 

You can also load styles similarly.

component.ts:

ngOnInit() { this.loadStyles(); } loadStyles() { const dynamicStyles = [ //styles to be loaded "assets/lib/css/ui.css", "assets/lib/css/material-theme.css", "assets/lib/css/custom-style.css" ]; for (let i = 0; i < dynamicStyles.length; i++) { const node = document.createElement('link'); node.href = dynamicStyles[i]; node.rel = 'stylesheet'; document.getElementById('styles').appendChild(node); } } 

component.html:

<div id="styles"> </div> 

1 Comment

So, in order to fix this issue, the OP should learn angular. Really?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.