Search code examples
javascriptdomevent-listener

How to use querySelector to remove a specific element from a list?


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)

[Increment Button] || [Decrement Nutton]


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. One heading, 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">Increment Number</button>

    <button id="decrement">Decrement Number</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 listOfItems = document.getElementById("list-items");

const counterValue = document.getElementById("counter-one");
let counter = 0;

function incrementValue() {
  counter++;
  counterValue.innerText = counter;

  //add a list item
  const li = document.createElement("li");
  li.innerHTML = "<b>Something</b> " + counter;
  li.setAttribute("data-counter", counter);
  listOfItems.appendChild(li);
  console.log(li);
}

function decrementValue() {
  counter--;
  counterValue.innerText = counter;
  //remove a list item
  const li = listOfItems.querySelector("[data-counter = " + counter + "]");

  li.remove();
}

incrementButton.addEventListener("click", incrementValue);
decrementButton.addEventListener("click", decrementValue);

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 lines:

listOfItems.querySelector("[data-counter = " + counter + "]");

li.remove();

used to "catch" the last added list-item,

are causing the following error: Uncaught DOMException: Failed to execute 'querySelector' on 'Element': '[data-counter = 1]' is not a valid selector. at HTMLButtonElement.decrementValue

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?


Solution

  • The counter should be wrapped in quotes (and no blank spaces!) when used in data attribute selector. Use instead Template Literals:

    ulElement.querySelector(`[data-counter="${counter}"]`);
    

    or, if you insist in double quotes escape them with backslash like:

    ulElement.querySelector("[data-counter=\""+ counter +"\"]");
    

    or, use single quotes to preserve double quotes like:

    ulElement.querySelector('[data-counter="'+ counter +'"]');