Кнопка удаления не работает после добавления еще одной записи в объект моей библиотеки - PullRequest
0 голосов
/ 03 августа 2020

У меня проблема с тем, что моя кнопка удаления (желтая) отлично работает с предварительно загруженными элементами библиотеки книг, но ее нет в новой записи, когда я добавляю книгу и хочу ее удалить ... Я также хочу, чтобы вы спросить, как проще всего удалить книги из массива myLibrary ... Спасибо.

Я прикрепил сюда свой код. Любая помощь будет оценена по достоинству. Заранее спасибо.

//DOM
const bookForm = document.querySelector(".book-form");

// Calling a form when clicking on add book button
function openNav() {
  document.getElementById("myNav").style.height = "100%";
  console.log("dsafsa");
}

function closeNav() {
  document.getElementById("myNav").style.height = "0%";
}

// where the books will be saved...
let myLibrary = [{
    title: "Harry Potter - and the Philosopher's Stone",
    author: "J. K. Rowling",
    pages: 223,
    readStatus: "no",
  },
  {
    title: "The Hobbit",
    author: "J.R.R. Tolkien",
    pages: 304,
    readStatus: "yes",
  },
];

// book object
function Book(title, author, pages, readStatus) {
  (this.title = title),
  (this.author = author),
  (this.pages = pages),
  (this.readStatus = readStatus);
}

let i = "";
// render the book on page load...
function render() {
  const books = myLibrary;
  books.forEach((book) => {
    addNewBookUI(book);
  });
}
render();

document.querySelector(".book-form").addEventListener("submit", (e) => {
  // prevent actual submit
  e.preventDefault();

  // get values
  const title = document.querySelector("#title").value;
  const author = document.querySelector("#author").value;
  const pages = document.querySelector("#pages").value;
  const readStatus = document.querySelector('input[name="yes_no"]:checked')
    .value;
  // prevent empty fields ...

  if (title === "" || author === "" || pages === "0") {
    alert("Missing data");
  } else {
    const book = new Book(title, author, pages, readStatus);
    myLibrary.push(book);
    addNewBookUI(book);
    clearFormFields()
  }
});

function addNewBookUI(book) {
  if (book.readStatus === "yes") {
    i = "checked";
  } else {
    i = "";
  }
  const main = document.querySelector(".main");
  const bookCard = document.createElement("div");
  bookCard.classList.add("book-card");
  bookCard.innerHTML = `<div class="delete_button"><button class="delete btn"><i class="fa fa-trash">
        </i></button></div><div class="title">${book.title}</div><div class="author">${book.author}
        </div><div class="pages">${book.pages}</div><div class="read_status">Read: <input type="checkbox" id="yes" name="readstatus" value="yes" ${i}> 
        </div>`;
  main.appendChild(bookCard);
}

// clear form fields after submit 
function clearFormFields() {
  const myForm = document.getElementById("myForm");
  myForm.reset();
}

// Add event listener to all deleteButton 
const deleteButton = document.querySelectorAll(".delete");

// deletes book UI;
deleteButton.forEach((el) => {
  el.addEventListener("click", function () {
    el.parentElement.parentElement.remove()
    console.log("sas")
  })
})
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  font-family: 'Roboto', sans-serif;
  margin: 0;
  padding: 0;
}

header {
  color: #ffffff;
  display: flex;
  font-size: 1.4rem;
  justify-content: space-between;
  align-items: center;
  background-color: #155999;
  border-bottom: #172f4f solid 10px;
}

.logo {
  margin-left: 10px;
}

header button {
  background-color: #183153;
  border: none;
  text-align: left;
  font-size: 0.9rem;
  border-radius: 5px;
  color: #ffffff;
  padding: 10px 50px;
  margin-right: 10px;
  cursor: pointer;
}

.plus-sign {
  padding-right: 7px;
}

.main {
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: #183153;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
}

.book-card {
  text-align: center;
  font-weight: 1000;
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  width: 250px;
  height: 350px;
  border-radius: 10px;
  background-color: #155999;
  margin-left: 20px;
  margin-top: 10px;
  color: #ffffff;
  border: #172f4f solid 8px;
  line-height: 30px;
  position: relative;
  padding-left: 7px;
  padding-right: 7px;
  box-shadow: 10px 4px 22px -5px rgba(21, 89, 153, 1);
}

.overlay {
  height: 0%;
  width: 100%;
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  background-color: rgb(21, 89, 153);
  background-color: rgba(21, 89, 153, 0.7);
  overflow-y: hidden;
  transition: 0.5s;
}

.overlay-content {
  position: relative;
  top: 25%;
  width: 100%;
  text-align: center;
  margin-top: 30px;
  display: flex;
  flex-direction: column;
  font-size: 30px;
}

.overlay a {
  padding: 8px;
  text-decoration: none;
  font-size: 36px;
  color: #ffffff;
  display: block;
  transition: 0.3s;
}

.overlay a:hover,
.overlay a:focus {
  color: #c3c6d1;
}

.overlay .closebtn {
  position: absolute;
  top: 20px;
  right: 45px;
  font-size: 60px;
}

@media screen and (max-height: 450px) {
  .overlay {
    overflow-y: auto;
  }
  .overlay a {
    font-size: 20px
  }
  .overlay .closebtn {
    font-size: 40px;
    top: 15px;
    right: 35px;
  }
}

.book-card div {
  margin-top: 15px;
}


/* Style buttons */

.btn {
  background-color: #ffd43b;
  /* Blue background */
  border: none;
  /* Remove borders */
  color: red;
  /* White text */
  padding: 12px 16px;
  /* Some padding */
  font-size: 16px;
  /* Set a font size */
  cursor: pointer;
  /* Mouse pointer on hover */
  border-radius: 50%;
  position: absolute;
  top: -20px;
  right: -15px;
}


/* Darker background on mouse-over */

.btn:hover {
  background-color: #183153;
}

.delete_button {
  top: 0;
  right: 0;
}

form div {
  margin-top: 15px;
  font-family: 'Roboto', sans-serif;
  color: white;
  font-weight: bold;
  font-size: 30px;
  margin-bottom: 10px;
}

.radiobutton {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.form-flex {
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
}

.form-flex input {
  width: 50%;
  border-radius: 5px;
  height: 30px;
  margin-top: 5px
}

.form-flex input::placeholder {
  text-align: center;
}

input[type=submit] {
  background-color: #183153;
  border: none;
  text-align: left;
  font-size: 0.9rem;
  border-radius: 5px;
  color: #ffffff;
  padding: 10px 50px;
  margin-top: -30px;
  cursor: pointer;
}

.radiobutton p {
  margin-top: 10px;
  margin-bottom: 30px;
}

.flexbuttons {
  display: flex;
  margin-top: -50px;
  margin-bottom: -25px;
}

input[type="text"] {
  font-size: 24px;
  text-align: center;
}
<!-- The overlay -->
<div id="myNav" class="overlay">
  <!-- Button to close the overlay navigation -->
  <a href="javascript:void(0)" class="closebtn" onclick="closeNav()">&times;</a>
  <!-- Overlay content -->
  <div class="overlay-content">
    <form  id="myForm" class="book-form">
      <div class="form-flex">
        <label for="title">Book name:</label>
        <input type="text" id="title" name="title" placeholder="Book name...">
      </div>
      <div class="form-flex">
        <label for="author">Book author:</label>
        <input type="text" id="author" name="author" placeholder="Book author...">
      </div >
      <div class="form-flex">
        <label for="pages">Pages:</label>
        <input type="number" id="pages" placeholder="0" name="pages">
      </div>
      <div class="radiobutton">
        <p>Have you read a book?</p>
        <div class="flexbuttons">
          <div>
            <p><input type="radio" id="huey" name="yes_no" value="yes" checked>
              <label for="huey">yes</label>
            </p>
          </div>
          <div>
            <p><input type="radio" id="no" name="yes_no" value="no">
              <label for="dewey">no</label>
            </p>
          </div>
        </div>
      </div>
      <div><input type="submit" value="Add Book"></div>
    </form>
  </div>
  </form>
</div>
</div>
</div>
<header>
  <div class="logo">
    <h1><i class="fa fa-book" aria-hidden="true"></i>
      </i>Library
    </h1>
  </div>
  <div class="button">
    <button onclick="openNav()" class="add-book">
    <i class="fa fa-plus plus-sign"></i>
    Add book</button>
  </div>
</header>
<div class="main">
</div>
<script src="./index.js" defer></script>
<script src="https://use.fontawesome.com/30a34909cc.js"></script>

1 Ответ

1 голос
/ 03 августа 2020

Вы назначили событие click во время загрузки всем существующим кнопкам с помощью class=="delete". Естественно, сюда не будут входить те, которые вы могли бы динамически добавлять на более позднем этапе.

Если вы хотите, чтобы все кнопки ".delete" имели привязанное к ним событие нажатия, вам необходимо сделать a «делегированное вложение события» ( отредактировано , теперь удаляет элемент myLibrary):

// Add event listener to all current and future deleteButtons
document.querySelector('.main').onclick=ev=>{
 let el= ev.target.classList.contains('fa-trash')? ev.target.parentElement : ev.target.classList.contains('delete') ? ev.target : false;
 if (el) {
   let card=el.parentElement.parentElement; // book-card DOM element
   // remove myLibrary array-element here:
   myLibrary.splice( [...card.parentElement.children].indexOf(card) ,1);
   console.log(myLibrary)
   // remove card DOM element:
   card.remove()
 }
}

Это привяжет обработчик события щелчка к .main div и будет реагировать только в том случае, если нажатый элемент имеет class=='fa-trash' или class=='delete'. В первом случае он «переместится» на один уровень (назначит родительский элемент, т.е. кнопку, на el), в противном случае нажатый элемент будет самой кнопкой. Если ни один из этих классов не найден, el становится false и ничего не происходит. В противном случае "дедушка" el удаляется с помощью `el.parentElement.parentElement.remove () '.

И пожалуйста, попробуйте сделать свой MCVE a little меньше в следующий раз, так как неинтересно обрабатывать такой объем кода в небольшом окне фрагмента Stackoverflow! Настоящий MCVE даст вам больше и быстрее ответов!

Ниже приведен рабочий фрагмент, проверьте его:

//DOM
const bookForm = document.querySelector(".book-form");

// Calling a form when clicking on add book button
function openNav() {
  document.getElementById("myNav").style.height = "100%";
  console.log("dsafsa");
}

function closeNav() {
  document.getElementById("myNav").style.height = "0%";
}

// where the books will be saved...
let myLibrary = [
  {
    title: "Harry Potter - and the Philosopher's Stone",
    author: "J. K. Rowling",
    pages: 223,
    readStatus: "no",
  },
  {
    title: "The Hobbit",
    author: "J.R.R. Tolkien",
    pages: 304,
    readStatus: "yes",
  },
];

// book object
function Book(title, author, pages, readStatus) {
  (this.title = title),
    (this.author = author),
    (this.pages = pages),
    (this.readStatus = readStatus);
}

let i = "";
// render the book on page load...
function render() {
  const books = myLibrary;
  books.forEach((book) => {
    addNewBookUI(book);
  });
}
render();

document.querySelector(".book-form").addEventListener("submit", (e) => {
  // prevent actual submit
  e.preventDefault();

  // get values
  const title = document.querySelector("#title").value;
  const author = document.querySelector("#author").value;
  const pages = document.querySelector("#pages").value;
  const readStatus = document.querySelector('input[name="yes_no"]:checked')
    .value;
  // prevent empty fields ...

  if (title === "" || author === "" || pages === "0") {
    alert("Missing data");
  } else {
    const book = new Book(title, author, pages, readStatus);
    myLibrary.push(book);
    addNewBookUI(book);
    clearFormFields()
  }
});

function addNewBookUI(book) {
  if (book.readStatus === "yes") {
    i = "checked";
  } else {
    i = "";
  }
  const main = document.querySelector(".main");
  const bookCard = document.createElement("div");
  bookCard.classList.add("book-card");
  bookCard.innerHTML = `<div class="delete_button"><button class="delete btn"><i class="fa fa-trash">
        </i></button></div><div class="title">${book.title}</div><div class="author">${book.author}
        </div><div class="pages">${book.pages}</div><div class="read_status">Read: <input type="checkbox" id="yes" name="readstatus" value="yes" ${i}> 
        </div>`;
  main.appendChild(bookCard);
}

// clear form fields after submit 
function clearFormFields() {
  const myForm = document.getElementById("myForm");
  myForm.reset();
}

// Add event listener to all deleteButton 
document.querySelector('.main').onclick=ev=>{
 let el= ev.target.classList.contains('fa-trash')? ev.target.parentElement : ev.target.classList.contains('delete') ? ev.target : false;
 if (el) {
   let card=el.parentElement.parentElement;
   myLibrary.splice( [...card.parentElement.children].indexOf(card) ,1);
   console.log(myLibrary)
   card.remove()
 }
}
*, *::before, *::after { 
     box-sizing: border-box; 
}

body {
    
    font-family: 'Roboto', sans-serif;
    margin: 0;
    padding: 0;
}

header {
    color: #ffffff;
    display: flex;
    font-size: 1.4rem;
    justify-content: space-between;
    align-items: center;
    background-color:#155999;
    border-bottom: #172f4f solid 10px;
}

.logo {
    margin-left: 10px;
}


header button {
    background-color: #183153;
    border: none;
    text-align: left;
    font-size: 0.9rem;
    border-radius: 5px;
    color: #ffffff;
    padding: 10px 50px;
    margin-right: 10px;
    cursor: pointer;
}

.plus-sign {
    padding-right: 7px;
}

.main {
    position: absolute;
    width: 100%;
    height: 100%;
    background-color: #183153;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    
}



.book-card {
    text-align: center;
    font-weight: 1000;
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
    width: 250px;
    height: 350px;
    border-radius: 10px;
    background-color: #155999;
    margin-left: 20px;
    margin-top:10px;
    color: #ffffff; 
    border: #172f4f solid 8px;
    line-height: 30px;
    position: relative;
    padding-left: 7px;
    padding-right: 7px;
    box-shadow: 10px 4px 22px -5px rgba(21,89,153,1);
}


.overlay {
  height: 0%;
  width: 100%;
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  background-color: rgb(21,89,153);
  background-color: rgba(21,89,153,0.7);
  overflow-y: hidden;
  transition: 0.5s;
  
}

.overlay-content {
  position: relative;
  top: 25%;
  width: 100%;
  text-align: center;
  margin-top: 30px;
  display: flex;
  flex-direction: column;
  font-size: 30px;
}

.overlay a {
  padding: 8px;
  text-decoration: none;
  font-size: 36px;
  color: #ffffff;
  display: block;
  transition: 0.3s;
}

.overlay a:hover, .overlay a:focus {
  color: #c3c6d1;
}

.overlay .closebtn {
  position: absolute;
  top: 20px;
  right: 45px;
  font-size: 60px;
}

@media screen and (max-height: 450px) {
  .overlay {overflow-y: auto;}
  .overlay a {font-size: 20px}
  .overlay .closebtn {
  font-size: 40px;
  top: 15px;
  right: 35px;
  }
} 

.book-card div {
    margin-top:15px;
}

 /* Style buttons */
 .btn {
    background-color: #ffd43b; /* Blue background */
    border: none; /* Remove borders */
    color: red; /* White text */
    padding: 12px 16px; /* Some padding */
    font-size: 16px; /* Set a font size */
    cursor: pointer; /* Mouse pointer on hover */
    border-radius: 50%;
    position:absolute; 
    top:-20px; 
    right:-15px;

  }
  
  /* Darker background on mouse-over */
  .btn:hover {
    background-color: #183153;
    
  } 

  .delete_button {
     
      top:0;
      right:0;
      
  }

  form div {
    margin-top: 15px;
    font-family: 'Roboto', sans-serif;
    color:white;
    font-weight: bold;
    font-size: 30px;
    margin-bottom: 10px;
  }

  .radiobutton {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }

  .form-flex {
    display: flex;
    justify-content: center;
    flex-direction: column;
    align-items: center;
  }
  
.form-flex input {
  width: 50%;
  border-radius: 5px;
  height: 30px;
  margin-top: 5px
}

.form-flex input::placeholder {
  text-align: center;

}

input[type=submit] {
  background-color: #183153;
    border: none;
    text-align: left;
    font-size: 0.9rem;
    border-radius: 5px;
    color: #ffffff;
    padding: 10px 50px;
    margin-top: -30px;
    cursor: pointer;

}

.radiobutton p {
  margin-top:10px;
  margin-bottom: 30px;  
}

.flexbuttons {
  display: flex;
  margin-top: -50px;
  margin-bottom: -25px;
}

input[type="text"]
{
    font-size:24px;
    text-align: center;
}
JS:

//DOM
const bookForm = document.querySelector(".book-form");
<!-- The overlay -->
    <div id="myNav" class="overlay">
    
        <!-- Button to close the overlay navigation -->
        <a href="javascript:void(0)" class="closebtn" onclick="closeNav()">&times;</a>
        
        <!-- Overlay content -->
        <div class="overlay-content">
            <form  id="myForm" class="book-form">
                <div class="form-flex">
                    <label for="title">Book name:</label>
                    <input type="text" id="title" name="title" placeholder="Book name...">
                </div>
                <div class="form-flex">
                    <label for="author">Book author:</label>
                    <input type="text" id="author" name="author" placeholder="Book author...">
                </div >
                <div class="form-flex">
                    <label for="pages">Pages:</label>
                    <input type="number" id="pages" placeholder="0" name="pages">
        
                </div>
        
                <div class="radiobutton">
                    <p>Have you read a book?</p>
                    <div class="flexbuttons">
                        <div><p><input type="radio" id="huey" name="yes_no" value="yes" checked>
                            <label for="huey">yes</label></p>
                           
                        </div>
                        
                        <div><p><input type="radio" id="no" name="yes_no" value="no">
                            <label for="dewey">no</label></p>
                            
                        </div>
                    </div>
                    
                </div>
        
                <div><input type="submit" value="Add Book"></div>
        
            </form>
        </div>
            
        
          </form>
          </div>
        </div>
  
  </div>
    
    <header>
        <div class="logo">
            <h1><i class="fa fa-book" aria-hidden="true"></i>
            </i>Library</h1>
        </div>
        <div class="button">
            
            <button onclick="openNav()" class="add-book">
                <i class="fa fa-plus plus-sign"></i>
                Add book</button>
        </div>
    </header>
    
    <div class="main">
        
        
    </div>

    <script src="./index.js" defer></script>
    <script src="https://use.fontawesome.com/30a34909cc.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...