I set up a webpage with two headings, and two buttons. The webpage looks exactly like the following before pressing on anything:
Counter-1 : (somenumber)
[button]
Counter-2: (somenumber)
[button]
If I click on the first button, the somenumber increments by 1.
If I click on the second button, the somenumber decrements by 1.
In addition, when I click on the first button(increment-button), a list-item gets added to the webpage. When I click on the second button(decrement-button), the last added list-item gets removed from the webpage.
Both buttons work and do their purpose (incrementing/decremnting wise), and when I click on the first button, a list-item indeed gets added to the webpage.
The problem occurs when I try to remove the last added list item, by pressing the second button, as described.
This is the html section. Nothing out of the ordinary. Two headings, and two buttons.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>Counter-1: <span id="counter-one">0</span></h1>
<button id="increment">click me</button>
<h1>Counter-2: <span id="counter-two">0</span></h1>
<button id="decrement">click me</button>
<ul id="list-items"></ul>
<script src="script.js" type="text/javascript"></script>
</body>
</html>
This is the JavaScript section. I get the two buttons from the HTML document, I set up an empty list on the HTML document, which I wanted to fill with one list-item per click on the first button (using javascript, hence making the button interactive).
const incrementButton = document.getElementById("increment");
const decrementButton = document.getElementById("decrement");
const ulElement = document.getElementById("list-items");
let counter = 0;
function incrementCounter() {
const counterInc = document.getElementById("counter-one");
counter++;
counterInc.innerText = counter;
//create an element
const li = document.createElement("li");
li.setAttribute("data-counter", counter);
li.innerHTML = "<b>Something</b> " + counter;
console.log(li);
//append it to the list
ulElement.appendChild(li);
}
function decrementCounter() {
//remove an element
const li = ulElement.querySelector("[data-counter = " + counter + "]");
li.remove();
const counterDec = document.getElementById("counter-two");
counter--;
counterDec.innerText = counter;
}
incrementButton.addEventListener("click", incrementCounter);
decrementButton.addEventListener("click", decrementCounter);
The mechanism of incrementing and decrementing the value is working properly, and the appending of the list-items works as well, as mentioned.
But the line:
const li = ulElement.querySelector("[data-counter = " + counter + "]");
used to "catch" the last added list-item,
is causing the following error:
Uncaught DOMException: Failed to execute 'querySelector' on 'Element': '[data-counter = 4]' is not a valid selector. at HTMLButtonElement.decrementCounter
And I don’t understand why the querySelector is invalid. I am certain that I have written something incorrect, or perhaps, an obsolete statement. How can I fix it?
3
Answers
The
counter
should be wrapped in quotes (and no blank spaces!) when used in data attribute selector. Use instead Template Literals:or, if you insist in double quotes escape them with backslash like:
or, use single quotes to preserve double quotes like:
Adding quotation marks before and after the
counter
variable appears to fix the query selector error. Change the line to 1 of the 3 lines below:You could also use a template literal, as mentioned by Roko C. Buljan above.
Your selector is off just a bit. You had
but it needs to have quotes around the value added like this, and probably remove the spaces around the
=
as well