Home > Net >  Adding eventListener to the newly created element
Adding eventListener to the newly created element

Time:12-29

there are several questions like this but can't find the answer. I'm tring to create some HTML elements after pressing the button and add eventListener to the checkbox right after creating it , but it does nothing. Can't find out what is the reason, it does not return any error . . .

and I'm getting this annoying message : It looks like your post is mostly code; please add some more details. There is nothing to add :) if I clear the code in the input area it disappears from the snippet

let addTaskBtn = document.querySelector('.inputPlusSign')
let tasksAreaDiv = document.querySelector('.tasksArea')
let inputText = document.querySelector('#taskInput')

addTaskBtn.addEventListener('click', function() {
  let taskWrapperDiv = document.createElement('div')
  taskWrapperDiv.setAttribute('class', 'taskWrapper')

  let taskDiv = document.createElement('div')
  taskDiv.setAttribute('class', 'task')

  let label = document.createElement('label')
  label.setAttribute('class', 'checkContainer')

  let checkBox = document.createElement('input')
  checkBox.setAttribute('type', 'checkbox')
  checkBox.setAttribute('class', 'taskCheckBox')

  let checkBoxSpan = document.createElement('span')
  checkBoxSpan.setAttribute('class', 'checkmark')

  let taskTextSpan = document.createElement('span')
  taskTextSpan.setAttribute('class', 'taskText')
  taskTextSpan.innerText = inputText.value

  label.appendChild(checkBox)
  label.appendChild(checkBoxSpan)

  taskDiv.appendChild(label)
  taskDiv.appendChild(taskTextSpan)
  taskDiv.innerHTML  = `<i ></i>`

  taskWrapperDiv.appendChild(taskDiv)

  tasksAreaDiv.appendChild(taskWrapperDiv)

  checkBox.addEventListener('click', function() {
    console.log('any text')
  })

})
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background-color: rgb(9, 9, 34);
  color: white;
  font-size: 1.5rem;
}

.main {
  width: 70%;
  margin: auto;
}

.wrapper {
  width: 60%;
  margin: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.title {
  padding: 1rem 0;
}

.inputWrapper {
  width: 100%;
  position: relative;
}

#taskInput {
  width: 100%;
  padding: 7px 50px 7px 20px;
  border-radius: 40px;
  font-size: 1.2rem;
  background-color: #dab979;
  border: none;
  caret-color: hsla(196, 43%, 33%, 1);
  color: white;
}

#taskInput:focus {
  outline-offset: 2px;
}

#taskInput::placeholder {
  color: white;
}

.inputPlusSign {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  margin-right: 15px;
  font-weight: bold;
  font-size: 20px;
  color: #fcedd3;
  cursor: pointer;
}

.inputPlusSign:active {
  color: white;
}

.tasksArea {
  width: 95%;
  background-color: hsla(196, 43%, 33%, 0.5);
  min-height: 300px;
  margin-top: 1rem;
  padding-bottom: 2rem;
}

.taskWrapper {
  border-bottom: 1px solid black;
}

.task {
  padding: 1rem 3rem;
  position: relative;
}

.checkContainer {
  user-select: none;
}

.taskCheckBox {
  position: absolute;
  opacity: 0;
  cursor: pointer;
  height: 0;
  width: 0;
}

.checkmark {
  position: absolute;
  top: 50%;
  left: 1rem;
  transform: translateY(-50%);
  height: 20px;
  width: 20px;
  background-color: #dab979;
  box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
}

.checkContainer:hover .taskCheckBox~.checkmark {
  background-color: #fcedd3;
}

.checkContainer .taskCheckBox:checked~.checkmark {
  background-color: #dab979;
}

.checkmark:after {
  content: "";
  position: absolute;
  display: none;
}

.checkContainer .taskCheckBox:checked~.checkmark:after {
  display: block;
}

.checkContainer:has(.taskCheckBox:checked)~.taskText {
  text-decoration: line-through;
}

.checkContainer .checkmark:after {
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid #fcedd3;
  border-width: 0 3px 3px 0;
  transform: rotate(45deg);
}

.taskText {
  margin-left: 10px;
}

.trashCan {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  margin-right: 1rem;
  color: #dab979;
  cursor: pointer;
}

.trashCan:hover {
  color: #fcedd3;
}

.taskText {
  overflow-wrap: break-word;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" rel="stylesheet" />
<div >
  <div >
    <h3 >Type your task here . . .</h3>
    <div >
      <input type="text" id="taskInput" placeholder="What's your focus for today?">
      <i ></i>
    </div>
    <div >
    </div>
  </div>
</div>

CodePudding user response:

The source of the problem is the switch from .appendChild() to .innerHTML.

taskDiv.innerHTML  = `<i ></i>`

After this line the reference in checkBox points to a different <input type="checkbox" /> element, because you've overwritten it.

(checkBox === taskDiv.querySelector('input[type="checkbox"]') // -> false)

Either use .createElement() and .appendChild() or .insertAdjacentHTML() to add the <i> element:

taskDiv.insertAdjacentHTML("beforeend", '<i ></i>');

let addTaskBtn = document.querySelector('.inputPlusSign')
let tasksAreaDiv = document.querySelector('.tasksArea')
let inputText = document.querySelector('#taskInput')

addTaskBtn.addEventListener('click', function() {
  let taskWrapperDiv = document.createElement('div')
  taskWrapperDiv.setAttribute('class', 'taskWrapper')

  let taskDiv = document.createElement('div')
  taskDiv.setAttribute('class', 'task')

  let label = document.createElement('label')
  label.setAttribute('class', 'checkContainer')

  let checkBox = document.createElement('input')
  checkBox.setAttribute('type', 'checkbox')
  checkBox.setAttribute('class', 'taskCheckBox')

  let checkBoxSpan = document.createElement('span')
  checkBoxSpan.setAttribute('class', 'checkmark')

  let taskTextSpan = document.createElement('span')
  taskTextSpan.setAttribute('class', 'taskText')
  taskTextSpan.innerText = inputText.value

  label.appendChild(checkBox)
  label.appendChild(checkBoxSpan)

  taskDiv.appendChild(label)
  taskDiv.appendChild(taskTextSpan)
  taskDiv.insertAdjacentHTML("beforeend", `<i ></i>`);

  taskWrapperDiv.appendChild(taskDiv)

  tasksAreaDiv.appendChild(taskWrapperDiv)

  checkBox.addEventListener('click', function() {
    console.log('any text')
  })

})
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background-color: rgb(9, 9, 34);
  color: white;
  font-size: 1.5rem;
}

.main {
  width: 70%;
  margin: auto;
}

.wrapper {
  width: 60%;
  margin: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.title {
  padding: 1rem 0;
}

.inputWrapper {
  width: 100%;
  position: relative;
}

#taskInput {
  width: 100%;
  padding: 7px 50px 7px 20px;
  border-radius: 40px;
  font-size: 1.2rem;
  background-color: #dab979;
  border: none;
  caret-color: hsla(196, 43%, 33%, 1);
  color: white;
}

#taskInput:focus {
  outline-offset: 2px;
}

#taskInput::placeholder {
  color: white;
}

.inputPlusSign {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  margin-right: 15px;
  font-weight: bold;
  font-size: 20px;
  color: #fcedd3;
  cursor: pointer;
}

.inputPlusSign:active {
  color: white;
}

.tasksArea {
  width: 95%;
  background-color: hsla(196, 43%, 33%, 0.5);
  min-height: 300px;
  margin-top: 1rem;
  padding-bottom: 2rem;
}

.taskWrapper {
  border-bottom: 1px solid black;
}

.task {
  padding: 1rem 3rem;
  position: relative;
}

.checkContainer {
  user-select: none;
}

.taskCheckBox {
  position: absolute;
  opacity: 0;
  cursor: pointer;
  height: 0;
  width: 0;
}

.checkmark {
  position: absolute;
  top: 50%;
  left: 1rem;
  transform: translateY(-50%);
  height: 20px;
  width: 20px;
  background-color: #dab979;
  box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
}

.checkContainer:hover .taskCheckBox~.checkmark {
  background-color: #fcedd3;
}

.checkContainer .taskCheckBox:checked~.checkmark {
  background-color: #dab979;
}

.checkmark:after {
  content: "";
  position: absolute;
  display: none;
}

.checkContainer .taskCheckBox:checked~.checkmark:after {
  display: block;
}

.checkContainer:has(.taskCheckBox:checked)~.taskText {
  text-decoration: line-through;
}

.checkContainer .checkmark:after {
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid #fcedd3;
  border-width: 0 3px 3px 0;
  transform: rotate(45deg);
}

.taskText {
  margin-left: 10px;
}

.trashCan {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  margin-right: 1rem;
  color: #dab979;
  cursor: pointer;
}

.trashCan:hover {
  color: #fcedd3;
}

.taskText {
  overflow-wrap: break-word;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" rel="stylesheet" />
<div >
  <div >
    <h3 >Type your task here . . .</h3>
    <div >
      <input type="text" id="taskInput" placeholder="What's your focus for today?">
      <i ></i>
    </div>
    <div >
    </div>
  </div>
</div>

CodePudding user response:

I don't recommend adding a new event listener for each new element. Instead, add an event listener to a parent <div> and use event propagation to listen only to elements that have that checkbox class. Like this:

let addTaskBtn = document.querySelector('.inputPlusSign')
let tasksAreaDiv = document.querySelector('.tasksArea')
let inputText = document.querySelector('#taskInput')

document.querySelector('.tasksArea').addEventListener('click', e => {
  if (!e.target.classList.contains('taskCheckBox')) return;
  const el = e.target;
  console.log(e.target   ' was clicked!');
});

addTaskBtn.addEventListener('click', function() {
  let taskWrapperDiv = document.createElement('div')
  taskWrapperDiv.setAttribute('class', 'taskWrapper')

  let taskDiv = document.createElement('div')
  taskDiv.setAttribute('class', 'task')

  let label = document.createElement('label')
  label.setAttribute('class', 'checkContainer')

  let checkBox = document.createElement('input')
  checkBox.setAttribute('type', 'checkbox')
  checkBox.setAttribute('class', 'taskCheckBox')

  let checkBoxSpan = document.createElement('span')
  checkBoxSpan.setAttribute('class', 'checkmark')

  let taskTextSpan = document.createElement('span')
  taskTextSpan.setAttribute('class', 'taskText')
  taskTextSpan.innerText = inputText.value

  label.appendChild(checkBox)
  label.appendChild(checkBoxSpan)

  taskDiv.appendChild(label)
  taskDiv.appendChild(taskTextSpan)
  taskDiv.innerHTML  = `<i ></i>`

  taskWrapperDiv.appendChild(taskDiv)

  tasksAreaDiv.appendChild(taskWrapperDiv)
})
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background-color: rgb(9, 9, 34);
  color: white;
  font-size: 1.5rem;
}

.main {
  width: 70%;
  margin: auto;
}

.wrapper {
  width: 60%;
  margin: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.title {
  padding: 1rem 0;
}

.inputWrapper {
  width: 100%;
  position: relative;
}

#taskInput {
  width: 100%;
  padding: 7px 50px 7px 20px;
  border-radius: 40px;
  font-size: 1.2rem;
  background-color: #dab979;
  border: none;
  caret-color: hsla(196, 43%, 33%, 1);
  color: white;
}

#taskInput:focus {
  outline-offset: 2px;
}

#taskInput::placeholder {
  color: white;
}

.inputPlusSign {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  margin-right: 15px;
  font-weight: bold;
  font-size: 20px;
  color: #fcedd3;
  cursor: pointer;
}

.inputPlusSign:active {
  color: white;
}

.tasksArea {
  width: 95%;
  background-color: hsla(196, 43%, 33%, 0.5);
  min-height: 300px;
  margin-top: 1rem;
  padding-bottom: 2rem;
}

.taskWrapper {
  border-bottom: 1px solid black;
}

.task {
  padding: 1rem 3rem;
  position: relative;
}

.checkContainer {
  user-select: none;
}

.taskCheckBox {
  position: absolute;
  opacity: 0;
  cursor: pointer;
  height: 0;
  width: 0;
}

.checkmark {
  position: absolute;
  top: 50%;
  left: 1rem;
  transform: translateY(-50%);
  height: 20px;
  width: 20px;
  background-color: #dab979;
  box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
}

.checkContainer:hover .taskCheckBox~.checkmark {
  background-color: #fcedd3;
}

.checkContainer .taskCheckBox:checked~.checkmark {
  background-color: #dab979;
}

.checkmark:after {
  content: "";
  position: absolute;
  display: none;
}

.checkContainer .taskCheckBox:checked~.checkmark:after {
  display: block;
}

.checkContainer:has(.taskCheckBox:checked)~.taskText {
  text-decoration: line-through;
}

.checkContainer .checkmark:after {
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid #fcedd3;
  border-width: 0 3px 3px 0;
  transform: rotate(45deg);
}

.taskText {
  margin-left: 10px;
}

.trashCan {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  margin-right: 1rem;
  color: #dab979;
  cursor: pointer;
}

.trashCan:hover {
  color: #fcedd3;
}

.taskText {
  overflow-wrap: break-word;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" rel="stylesheet" />
<div >
  <div >
    <h3 >Type your task here . . .</h3>
    <div >
      <input type="text" id="taskInput" placeholder="What's your focus for today?">
      <i ></i>
    </div>
    <div >
    </div>
  </div>
</div>

  • Related