Library Project requesting help on creating books

Hi All,

I’m having trouble with creating the books within the array. When I add a new book, the class created is the same, when I am attempting to loop through the classes to have multiple classes so removing them would be easier.

Since only class bookmark0 is being created, my remove button is attaching itself to the first

even though the second remove button still removes the second book in the image.

I also tried displaying the entire array instead after removing let myLibrary = [] from the event listener, but it would post the books exponentially. eg 0 0 1 0 1 2 0 1 2 3 4…

Any help is appreciated; I’ve been stuck on this for days.

Thanks!

function Book(title, author, pages, read){
this.title = title
this.author = author
this.pages = pages
this.read = read
this.sayName = function() {
console.log(title)
}
}

function addBookToLibrary() {
myLibrary.push(Book);
}

// function readerPrompt() {
// title = prompt(‘What is the name of your Book?’);
// author = prompt(‘Who is the author?’);
// pages = prompt(‘How many pages are in your book?’);
// read = prompt(‘Did you finish reading the book?’);

// }

function form(){
const bookId = document.getElementById(‘bookId’)
const authorId = document.getElementById(‘authorId’)
const pagesId = document.getElementById(‘pagesId’)
const checkboxId = document.getElementById(‘checkboxId’)

title = bookId.value
author = authorId.value
pages = pagesId.value
read = checkboxId.value

}

const btn = document.querySelector(’#new’);

let myLibrary = [];

btn.addEventListener(‘click’, () => {
let myLibrary = []
// readerPrompt()
form()

const newBook = new Book(title, author, pages, read)
myLibrary.push(newBook);
console.log(myLibrary)



for(i = 0; i < myLibrary.length; i++){
    
    
    
    const bookShelf = document.querySelector('#bookshelf')
    
    
    
    
    const logBook = document.createElement('p')
    
    logBook.classList.add('bookmark' + i)
    
    logBook.innerHTML = myLibrary[i].title + '<br></br>' + myLibrary[i].author + '<br></br>' + myLibrary[i].pages.toString() +'<br></br>' + '<input type="checkbox"/>' + myLibrary[i].read + '<br></br>'
    
    bookShelf.appendChild(logBook)
    console.log(myLibrary[i].title, myLibrary[i].author, myLibrary[i].pages, myLibrary[i].read)

    
    const remove = document.querySelector('.bookmark' + i)
    const removeButton = document.createElement('button')
        
    removeButton.addEventListener('click', () => {
        bookshelf.removeChild(logBook)
        bookshelf.removeChild(removeButton)
    })
    removeButton.classList.add('remove' + i)
    removeButton.textContent = 'REMOVE'
    remove.appendChild(removeButton)
        
    

   
}

})

Hi, try with let i = 0 inside the for

If this isn’t the problem try the lines

 console.log(`This is the  i value: ${i}`)
 console.log(`This is the class: bookmark`+i)

inside the for to check the values are correct.

Hope this will help.

Pd.: Looking the code a second time i am very suspicious of the line

because the const, im not sure if in the second loop you can replace the content of the variable logBook.

If the console doesn’t throw an error in this line its fine but im not 100% what hapens with this line inside a for loop. If this line works let me know

Thanks for the reply!

After trying let i = 0, nothing has changed, or at least from what I’ve noticed running the program.

I’ve attached the console.logs. The const didn’t show any errors and it continues to make a new ‘p’ element but the loop keeps outputting 0 because myLibrary = [] was placed during the event listener.

The content is also changing too since I’ve tried putting other values. I’m not sure if there’s some logic I don’t understand or if there’s a small error creeping somewhere.

But, when I remove that myLibrary = [], it would print out the array over and over again like this.


Maybe is for this.

you have an array myLibrary defined inside the event handler. When click the button the array is created but this new array isnt the same myLibrary you declare outside the function.

Also myLibrary isnt the same array you can create the next time you click the button. The first myLibrary only is accesible inside the first function call, and the second myLibrary is accesible only in the second function call. Maybe sound a bit confusing tell me if you understand this part.

Each time you click the button an empty array is created and you push only one element inside the array. So the for loop runs only one time adding only the class with 0.

A solution could be set the array as a global variable (outside any fucntion) and deleting the defintion inside the event handler. In this way any event handler add elements to the same myLibrary.

Maybe doing this you would have problem whit the line

   bookShelf.appendChild(logBook)

because now each time you press the button it appends all elements inside the array. To avoid this you could clear the bookShelf div before the for loop with

   bookShelf.innerHTML = "";

or only append the last element.

1 Like

Thank you so much!

Your suspicions were right. After setting bookShelf.innerHTML = “”;
All I needed to do was to remove the logBook since my button was inside logBook.

I also added a splice method to remove elements within my array since it would be looping everytime and still show the previous ones (0, 0 1, 0 1 2,…etc).

So far the issue is fixed, but going forward, is it good practice to use global variables and simply deleting previous nodes from the loop that caused duplication?

I’ve read that you shouldn’t really use global variables unless you have to. In this case, a global should be fine since it is a small program right?

 removeButton.addEventListener('click', () => {
            bookshelf.removeChild(logBook)
            //bookshelf.removeChild(removeButton)
            myLibrary.splice(i, 1)
        })

Of course, probably its because you can modify it from any part of the code including in parts with no relation with these variables. Its a good solution to share variables beteween diferent fuctions but it could generate problems hard to find.
In the next lessons (i think) you can find a better alterative to use global variables.

No, i think isnt a good practice. Deleting something to add it instantly doest sound good (I should stop doing it). The best option i think is to find a way to add only the elements not rendered in the page.
A good question could be: i need the iteration for all books each time a book is added?

Noted! Working with object constructors was a little tricky for me since it wasn’t as simple as

if(object is not in array){
append object to bookShelf div
}

using the array as a conditional instead of accessing it within the loop.

or maybe it is that simple?

Thank you for your help!

I wat thinking if i need to loop the array of books if the books are already in in the page.

Maybe the only thing you need is to add the last element in the array as child of bookShelf without deleting the content.