i'm currently working on an etch-a-sketch on the odin project. Here's the code I've come up with.
const container = document.querySelector(".container");
const input = document.querySelector("input");
const submitBtn = document.querySelector("button");
function createGrid() {
let value=input.value;
for (let i = 0; i < value; i++) {
const createDivRow = document.createElement("div");
createDivRow.classList.add("gridrow")
createDivRow.textContent = i;
container.appendChild(createDivRow);
}
}
function createGridItems() {
let value = input.value;
for (let i = 0; i < value; i++) {
const divRow = document.querySelectorAll(".gridrow");
const createDivItem = document.createElement("div");
createDivItem.textContent = "aa";
divRow.appendChild(createDivItem);
}
}
submitBtn.addEventListener("click", createGrid);
submitBtn.addEventListener("click", createGridItems);
In the createGrid() function, I aim to create n number of divs(n being the user input from an input textbox), which I have succeeded. The result was n number of divs with class="gridrow" in the con†ainer.
In the createGridItems() function, I'd like to put the same number of divs "n" into each .gridrow row(which I've given the variable divRow).
I tried declaring const divRow = document.querySelector(".gridRow")
and the result was n number of divs in the FIRST .gridrow div, which is almost what I wanted.
So, I figured I'd declare const divRow = document.querySelectorAll(".gridrow")
to target all the .gridrow I've created and put n number of divs into EACH .gridrow div. As a result, all I got was just empty n number of .gridrow divs, without the divs that I want.
Can anyone tell me where I've gone wrong ? I was sure the code above would work because I've already targeted all the .divrow divs when I declare divRow = document.querySelectorAll(".gridrow").
Thank you!
document.querySelectorAll
returns a NodeList (a collection of elements).
If you checked the javascript console, your code throws an error when trying to .appendChild
over the collection.
You instead needed to iterate over that collection and for each item (being a .gridrow
) append there a number of elements.
https://developer.mozilla.org/en-US/docs/Web/API/NodeList
Note: Although NodeList is not an Array, it is possible to iterate over it with forEach(). It can also be converted to a real Array using Array.from().
This is a quick demo:
const container = document.querySelector(".container");
const input = document.querySelector("input");
const submitBtn = document.querySelector("button");
function createGrid() {
const value = input.value;
for (let i = 0; i < value; i++) {
const createDivRow = document.createElement("div");
createDivRow.classList.add("gridrow")
createDivRow.textContent = i;
container.appendChild(createDivRow);
}
}
function createGridItems() {
const value = input.value;
//here you select the rows as .gridrow elements
const divRows = document.querySelectorAll(".gridrow");
//iterate over each one of them
divRows.forEach(divRow =>{
//and append to it a new div for as many times as the value fetched from the input element
for(let i=0;i < value; i++){
const createDivItem = document.createElement("div");
createDivItem.textContent = "aa";
divRow.appendChild(createDivItem);
}
});
}
submitBtn.addEventListener("click", createGrid);
submitBtn.addEventListener("click", createGridItems);
.gridrow{
border: solid 1px;
margin-top: 1em;
}
.gridrow > div {
border: solid 1px red;
margin-left: 1em;
display: inline-block;
}
<div class="container"></div>
<input type="text">
<button>submit</button>
And finally since the performance became a concern among the comments, here is a performance test to show the difference in time for each solution:
const numElements = 1000;
function addDivsOneByOne(containerId) {
const container = document.getElementById(containerId);
for (let i = 0; i < numElements; i++) {
const div = document.createElement('div');
div.textContent = `${i + 1}`;
container.appendChild(div);
}
}
function addDivsInBatch(containerId) {
const container = document.getElementById(containerId);
const fragment = document.createDocumentFragment();
for (let i = 0; i < numElements; i++) {
const div = document.createElement('div');
div.textContent = `${i + 1}`;
fragment.appendChild(div);
}
container.appendChild(fragment);
}
function addDivsUsingInnerHTML(containerId) {
const container = document.getElementById(containerId);
let html = '';
for (let i = 0; i < numElements; i++) {
html += `<div>${i + 1}</div>`;
}
container.innerHTML = html;
}
function runBenchmark() {
document.getElementById('container1').innerHTML = '';
document.getElementById('container2').innerHTML = '';
document.getElementById('container3').innerHTML = '';
const results = [];
// Measure addDivsOneByOne
let start = performance.now();
addDivsOneByOne('container1');
let end = performance.now();
results.push(`addDivsOneByOne took ${end - start} milliseconds.`);
// Measure addDivsInBatch
start = performance.now();
addDivsInBatch('container2');
end = performance.now();
results.push(`addDivsInBatch took ${end - start} milliseconds.`);
// Measure addDivsUsingInnerHTML
start = performance.now();
addDivsUsingInnerHTML('container3');
end = performance.now();
results.push(`addDivsUsingInnerHTML took ${end - start} milliseconds.`);
// Display results
document.getElementById('results').innerHTML = results.join('<br>');
}
.container {
border: 1px solid #ccc;
padding: 10px;
margin: 10px 0;
}
.container div {
margin: 2px 0;
}
<div id="results"></div>
<div class="container" id="container1"></div>
<div class="container" id="container2"></div>
<div class="container" id="container3"></div>
<div>
<button onclick="runBenchmark()">Run Benchmark</button>
</div>