skip to Main Content

FYI, I’m working on a basic web library interface that allows users to add book info and get that info displayed. After some debugging, I notice that my function responsible for taking the book info that people input didn’t function as I wanted. To be specific, document.getElementbyID() can’t seem to select my html <select> element even though it could select my input fields with no problems. In addition, it seems that the bookInfo variable is empty for some reasons unknown to me.

My CSS, for a more user-friendly design. There’s nothing wrong with it, just something to make viewing my preview a bit easier:

let myLibrary = [];

function Book(author,title,pages,readStatus) {
    this.author = author
    this.title = title 
    this.pages = pages 
    this.readStatus = readStatus
}

function addBooktoLibrary(book) {
    myLibrary.push(book)
}

document.querySelector('.new').addEventListener('click', ()=>{
    document.getElementById('add-dialog').showModal()
})

document.getElementById('cancel').addEventListener('click', ()=>{
    document.getElementById('add-dialog').close()
}) 

function displayBook(bookInfo){
    const bookElement = document.createElement('div');
    const buttonDiv = document.createElement('div')
    const removeButton = document.createElement('button');
    removeButton.innerText = 'Remove'
    bookElement.innerHTML = `Title: ${bookInfo.title}<br> Author: ${bookInfo.author}<br> Pages: ${bookInfo.pages}<br> Status: ${bookInfo.readStatus}`;
    buttonDiv.appendChild(removeButton)
    buttonDiv.classList.add('buttonDiv')
    bookElement.appendChild(buttonDiv)
    bookElement.classList.add('book')
    removeButton.classList.add('remove')
    document.querySelector('.card-container').appendChild(bookElement);
}

function processInfo(){
    let bookInfo = []
    document.getElementById("confirmBtn").addEventListener('click', ()=>{
        author = document.getElementById("author")
        title = document.getElementById("title")
        pages = document.getElementById("pages")
        readStatus = document.getElementById('status') //Line in question
        readStatusInsert = readStatus.options[readStatus.selectedIndex]

        bookInfo[author] = author.value
        bookInfo[title] = title.value
        bookInfo[pages] = pages.value
        bookInfo[readStatusInsert] = readStatusInsert.text
    })
    let newBook = new Book(bookInfo.author, bookInfo.title, bookInfo.pages, bookInfo.readStatusInsert)
    addBooktoLibrary(newBook)
}
html{
    height: 100vh;
}

body{
    margin: 0;
    padding: 0;
    height: 100%;
}

.header{
    background-color: blue;
    height: 7%;
    display: flex;
    align-items: center;
}

.new{
    margin-left: 5vw;
    
}

.card-container{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
}

.book{
    display: flex;
    flex-direction: column;
    width: 20%;
    border: solid;
    margin: 15px;
}

.buttonDiv{
    display: flex;
    justify-content: center;
}

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

input, select{
    margin: 5px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="logic.js" defer></script>
    <title>Library</title>
    <link rel="stylesheet" href="styles.css" defer>
</head>
<body>
    <div class="header">
        <button class="new">New</button>
    </div>
    <div>
        <dialog id="add-dialog">
            <form>
                <label>Add book</label>
                <input type="text" placeholder="Author" id="author" required>
                <input type="text" placeholder="Title" id="title" required>
                <input type="number" placeholder="Pages" id="pages" min="10">
                <select id="status">
                    <option value="">Select your book status</option>
                    <option value="reading">Reading</option>
                    <option value="completed">Completed</option>
                    <option value="onhold">On-hold</option>
                    <option value="dropped">dropped</option>
                </select>
                <div>
                    <button id='cancel' formmethod="dialog">Cancel</button>
                    <button id="confirmBtn" type="button" onclick="processInfo()">Confirm</button>
                  </div>
            </form>
        </dialog>
    </div>
    <div class="card-container"></div>
</body>
</html>

3

Answers


  1. Here in script.js Change this

    
        bookInfo[author] = author.value;
        bookInfo[title] = title.value;
        bookInfo[pages] = pages.value;
        bookInfo[readStatus] = readStatusInsert.text;
    
    

    With:

    
        bookInfo["author"] = author.value;
        bookInfo["title"] = title.value;
        bookInfo["pages"] = pages.value;
        bookInfo["readStatus"] = readStatusInsert.text;
    
    

    In the addBooktoLibrary function, you are pushing the book parameter directly to myLibrary, which isn’t recommended. Instead, you should be pushing the book object you’ve just created. Change this:

    function addBooktoLibrary(book) {
      myLibrary.push(book);
    }
    

    To:

    
        function addBooktoLibrary(bookInfo) {
          const newBook = new Book(
            bookInfo.author,
            bookInfo.title,
            bookInfo.pages,
            bookInfo.readStatus
          );
          myLibrary.push(newBook);
        }
    
    

    Now, your processInfo function should only process the form data without the unnecessary event listener:

    
    function processInfo() {
      let bookInfo = {};
      author = document.getElementById("author");
      title = document.getElementById("title");
      pages = document.getElementById("pages");
      readStatus = document.getElementById("status");
      readStatusInsert = readStatus.options[readStatus.selectedIndex];
    
      bookInfo["author"] = author.value;
      bookInfo["title"] = title.value;
      bookInfo["pages"] = pages.value;
      bookInfo["readStatus"] = readStatusInsert.text;
    
      addBooktoLibrary(bookInfo);
    }
    

    Make these changes, and your code should work more accurately.

    Code should look like this :

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>Library</title>
      <style>
        html {
          height: 100vh;
        }
    
        body {
          margin: 0;
          padding: 0;
          height: 100%;
        }
    
        .header {
          background-color: blue;
          height: 7%;
          display: flex;
          align-items: center;
        }
    
        .new {
          margin-left: 5vw;
        }
    
        .card-container {
          display: flex;
          flex-direction: row;
          flex-wrap: wrap;
          justify-content: center;
        }
    
        .book {
          display: flex;
          flex-direction: column;
          width: 20%;
          border: solid;
          margin: 15px;
        }
    
        .buttonDiv {
          display: flex;
          justify-content: center;
        }
    
        form {
          display: flex;
          align-items: center;
          flex-direction: column;
        }
    
        input,
        select {
          margin: 5px;
        }
      </style>
    </head>
    <body>
      <div class="header">
        <button class="new">New</button>
      </div>
      <div>
        <dialog id="add-dialog">
          <form>
            <label>Add book</label>
            <input type="text" placeholder="Author" id="author" required />
            <input type="text" placeholder="Title" id="title" required />
            <input type="number" placeholder="Pages" id="pages" min="10" />
            <select id="status">
              <option value="">Select your book status</option>
              <option value="reading">Reading</option>
              <option value="completed">Completed</option>
              <option value="onhold">On-hold</option>
              <option value="dropped">dropped</option>
            </select>
            <div>
              <button id="cancel" formmethod="dialog">Cancel</button>
              <button id="confirmBtn" type="button" onclick="processInfo()">
                Confirm
              </button>
            </div>
          </form>
        </dialog>
      </div>
      <div class="card-container"></div>
      <script>
        let myLibrary = [];
    
        function Book(author, title, pages, readStatus) {
          this.author = author;
          this.title = title;
          this.pages = pages;
          this.readStatus = readStatus;
        }
    
        function addBooktoLibrary(bookInfo) {
          const newBook = new Book(
            bookInfo.author,
            bookInfo.title,
            bookInfo.pages,
            bookInfo.readStatus
          );
          myLibrary.push(newBook);
        }
    
        document.querySelector(".new").addEventListener("click", () => {
          document.getElementById("add-dialog").showModal();
        });
    
        document.getElementById("cancel").addEventListener("click", () => {
          document.getElementById("add-dialog").close();
        });
    
        function displayBook(bookInfo) {
          const bookElement = document.createElement("div");
          const buttonDiv = document.createElement("div");
          const removeButton = document.createElement("button");
          removeButton.innerText = "Remove";
          bookElement.innerHTML = `Title: ${bookInfo.title}<br> Author: ${bookInfo.author}<br> Pages: ${bookInfo.pages}<br> Status: ${bookInfo.readStatus}`;
          buttonDiv.appendChild(removeButton);
          buttonDiv.classList.add("buttonDiv");
          bookElement.appendChild(buttonDiv);
          bookElement.classList.add("book");
          removeButton.classList.add("remove");
          document.querySelector(".card-container").appendChild(bookElement);
        }
    
        function processInfo() {
          let bookInfo = {};
          author = document.getElementById("author");
          title = document.getElementById("title");
          pages = document.getElementById("pages");
          readStatus = document.getElementById("status");
          readStatusInsert = readStatus.options[readStatus.selectedIndex];
    
          bookInfo["author"] = author.value;
          bookInfo["title"] = title.value;
          bookInfo["pages"] = pages.value;
          bookInfo["readStatus"] = readStatusInsert.text;
    
          addBooktoLibrary(bookInfo);
          displayBook(bookInfo);
          document.getElementById("add-dialog").close();
        }
      </script>
    </body>
    </html>
    
    

    These Are the Best practices 😉

    Login or Signup to reply.
  2. Based on my testing all the values were being properly fetched, including for the select. However, the bookInfo variable was not storing the values correctly.

    The indexes for bookinfo were not in strings so they were taking the HTML element variables as the index and that was creating some issues.

    Try replacing the code below

    bookInfo[author] = author.value
    bookInfo[title] = title.value
    bookInfo[pages] = pages.value
    bookInfo[readStatusInsert] = readStatusInsert.text
    

    To the following

    bookInfo['author'] = author.value
    bookInfo['title'] = title.value
    bookInfo['pages'] = pages.value
    bookInfo['readStatusInsert'] = readStatusInsert.text
    

    bookInfo is populated correctly post this correction

    Login or Signup to reply.
  3. In arrays, we cannot do that:

    bookInfo[author] = author.value
    bookInfo[title] = title.value
    bookInfo[pages] = pages.value
    bookInfo[readStatusInsert] = readStatusInsert.text
    

    Instead I recommend putting it an object, then push it

    let book = {
      author: author.value
      title: title.value
      pages: page.value
      readStatusInsert: readStatusInsert.text
    }
    bookInfo.push(book);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search