Put simply, I’ve tried the async and defer methods, as well as moving the script tag, to try to get dom manipulation to work. I think it might just be the code since neither are solving the issue. I copy pasted code directly from an example on The Odin Project, so I’m not quite sure what’s going wrong. Below are the HTML and JS files.
const container = document.querySelector('#container');
const content = document.createElement('div');
content.classList.add('content');
content.textContent = 'This is the glorious text-content!';
container.appendChild(content);
const para = document.createElement('p');
para.classList.add('para');
para.textContent = 'This is the fun times!';
container.appendChild(para);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM Manipulation</title>
<script defer src="index.js"></script>
</head>
<body>
<h1>
THE TITLE OF YOUR WEBPAGE
</h1>
<div className="container"></div>
</body>
</html>
To be more specific, the entire section after the first appendChild is basically useless, and could be removed for the time being. The specific error is "Uncaught TypeError: Cannot read properties of null (reading ‘appendChild’)" at index.js:8:11.
I’ve tried changing the way I write the code as well, but I cannot understand why this is an issue even when moving the script link to the bottom and using async + defer all at the same time. I’ve tried every combo of the 3 solutions but I cannot get this to work.
I cannot quite figure out why it seems that the DOM is forcing itself to load faster than the HTML despite whatever I try to do to slow it down. I also did clear my cache, multiple times even, just to make sure it wasn’t a cache issue. I was running this test with the live server extension, making sure to save, and I even tried it loading as a local file instead.
At first, I had actually gotten the top part to work by mistyping the createElement("div") as a querySelector("div"), but then I tried to create the next element (the P) and that’s when I noticed that there was an error in the console when trying to see why my P wasn’t working (lol).
I know there are also some other potential fixes, the window.onload (idk the real spelling) and the addEventListener for when the window loads, but why would defer/async/bottom of HTML not work? It does not make any sense and I do not want to simply move on without understanding the issue.
>Solution :
You have a wrong class attribute and selector, fix:
className="container" -> class="container"
and
querySelector('#container') -> querySelector('.container')`
const container = document.querySelector('.container');
const content = document.createElement('div');
content.classList.add('content');
content.textContent = 'This is the glorious text-content!';
container.appendChild(content);
const para = document.createElement('p');
para.classList.add('para');
para.textContent = 'This is the fun times!';
container.appendChild(para);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM Manipulation</title>
<script defer src="index.js"></script>
</head>
<body>
<h1>
THE TITLE OF YOUR WEBPAGE
</h1>
<div class="container"></div>
</body>
</html>
or
className="container" -> id="container"
const container = document.querySelector('#container');
const content = document.createElement('div');
content.classList.add('content');
content.textContent = 'This is the glorious text-content!';
container.appendChild(content);
const para = document.createElement('p');
para.classList.add('para');
para.textContent = 'This is the fun times!';
container.appendChild(para);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM Manipulation</title>
<script defer src="index.js"></script>
</head>
<body>
<h1>
THE TITLE OF YOUR WEBPAGE
</h1>
<div id="container"></div>
</body>
</html>