Navigating a collection of objects after a button is clicked

My current library project involves looping through an array of objects to display them on a grid based on input values. Here is the code snippet for my loop:

const addBook = (ev) => {
    ev.preventDefault();
    let myLibrary = [];
    let bookInfo = {
      title: document.getElementById('title').value,
      author: document.getElementById('author').value,
      pages: document.getElementById('pages').value,
    }
    myLibrary.push(bookInfo)
    for (i = 0; i < myLibrary.length; i++) {
      console.log(myLibrary)
      var container = document.getElementById('book-shelf')
      var div = document.createElement('div')
      div.classList.add('cell')
      container.appendChild(div);
    }
    var submitBtn = document.querySelector('.submit-btn');
    submitBtn.addEventListener('click', addBook)

However, I'm facing an issue where every time I enter title, author, and pages values and click the submit button, it adds multiple cells instead of just one. For example, entering the information once gives me 3 cells, entering it again gives me 6 cells, and so on. How can I change my code to ensure that only one cell is added each time I submit a new book?

Answer №1

There are a few key issues that need to be addressed.

  1. The missing curly brace after the function and before the button listener is causing an error.

  2. myLibrary is being redefined each time the function is called, leading to unnecessary data retrieval. It is recommended to define it outside the function so that books can be added one at a time when addBook is executed.

  3. Since myLibrary is no longer being redefined, the loop can be eliminated. The HTML for the book can simply be added to the bookshelf onSubmit.

(Important: In the provided example code (with additional HTML elements, inputs, buttons, and logic to add new books to the shelf), the variable myLibrary has been renamed to

bookShelf</code to maintain consistency with the HTML naming convention.)</p>
<p><div>
<div>
<pre class="lang-js"><code>// Start by caching all required elements
const titleEl = document.getElementById('title');
const authorEl = document.getElementById('author');
const pagesEl = document.getElementById('pages');
const bookshelfEl = document.getElementById('bookshelf');
const submitBtn = document.querySelector('.submit-btn');

// Set up the event listener
submitBtn.addEventListener('click', addBook, false);

titleEl.focus();

// Declare the bookShelf variable outside of the function
const bookShelf = [];

function addBook() {

  // With cached elements, extract values easily
  const bookInfo = {
    title: titleEl.value,
    author: authorEl.value,
    pages: pagesEl.value,
  }

  bookShelf.push(bookInfo);

  // Extract individual variables from bookInfo
  const { title, author, pages } = bookInfo;

  // Create a row for the table data
  const row = document.createElement('tr')

  // Generate and append HTML to the table
  row.innerHTML = `
     <td>${title}</td>
     <td>${author}</td>
     <td>${pages}</td>
  `;

  bookshelfEl.appendChild(row);

}
table { border-collapse: collapse; border: 2px solid #565656; width: 100%; }
td { text-align: center; }
.heading { background-color: #efefef; border-top: solid thin #565656; }
tr { border: solid thin #ababab; }
<input placeholder="Title" id="title" />
<input placeholder="Author" id="author" />
<input placeholder="Pages" id="pages" />
<button type="button" class="submit-btn">Submit</btnotn>
<H3>Book shelf</H3>
<table>
  <tbody id="bookshelf">
    <tr class="heading">
      <td>Title</td>
      <td>Author</td>
      <td>Pages</td>
    </tr>
  </tbody>
</table>

Answer №2

The main issue lies within the loop structure in your code. Every time you click the submit button, a cell is added for each item in the myLibrary array. This repetitive process can be optimized by simply adding the cell directly when new book information is being added to myLibrary, eliminating the need for the for loop.

const addBook = (ev) => {
    ev.preventDefault();
    let myLibrary = [];
    let bookInfo = {
        title: document.getElementById('title').value,
        author: document.getElementById('author').value,
        pages: document.getElementById('pages').value,
    }
    myLibrary.push(bookInfo)
    var container = document.getElementById('book-shelf')
    var div = document.createElement('div')
    div.classList.add('cell')
    container.appendChild(div);
}
var submitBtn = document.querySelector('.submit-btn');
submitBtn.addEventListener('click', addBook)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it time to swap out those divs for tables in your email template?

I have set up my template like this and I am questioning whether I should replace every div with a table. Let's start with the first div in the example. Do I really need to create a new table element, followed by tr and td tags just for a banner? I u ...

Creating secure RSA keys using a predetermined seed - a step-by-step guide

Is it possible to utilize a unique set of words as a seed in order to recover a lost private key, similar to how cryptocurrency wallets function? This method can be particularly beneficial for end-to-end encryption among clients, where keys are generated o ...

JavaScript issue: "No relay configuration found" error specifically occurs in Internet Explorer versions 7 and 8

Encountering issues with loading JavaScript only on specific pages in Internet Explorer. Safari, Firefox, and Chrome render the page correctly. Debugging revealed the following errors: 1) No relay set (used as window.postMessage targetOrigin), cannot send ...

In Vue, the CropperJs image initially appears small, but it returns to its original size after editing

I encountered a peculiar issue while working on a website for image cropping using Vue.js and CropperJs. On the homepage, users can select an image to crop and proceed to the next page where a component named ImageCropper.vue is displayed. Strangely, the c ...

Issue with relative input causing Jquery click event to not fire

Jquery $(document).on("click","[type=text]",function(event) { alert('test'); }); CSS .noWorking:focus{ z-index:100; position:relative; outline:none; box-shadow:0 0 0 1000px rgba(0,0,0,.2); } To ensure the shadow appears on top of all oth ...

Ways to center Bootstrap panel in the middle of a webpage

Is there a way to center this entire panel on the web page? I could use some guidance with this. Does anyone have recommendations for a good book to learn Bootstrap design? <div class="panel panel-default" style="max-width:500px;margin-left:auto;margi ...

The method of iterating over a string in key-value pairs

How can I efficiently loop through a string and extract key/value pairs? The data is provided to me as a single string using the jstorage plugin. I attempted to split the string into an array, but the resulting key/values were not as expected. For exampl ...

I am eager to retrieve the outcome once all the queries have been completed within the loop (using express.js, react.js, and MySQL)

Currently, I am engaged in a personal project that involves using React and Express. The task at hand is to retrieve data spanning 7 days for a specific item from my database and present it in a search list. To achieve this, I attempted the following: U ...

How can I adjust the appearance of an HTML tag within an Angular component?

I have created an Angular component with the following definition: import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'rdc-dynamic-icon-button', templateUrl: './dynamic-icon-button. ...

Is it possible to create HTML tables without including paragraphs within the cells using docutils rst2html?

If my input rst file looks like this: +--------------------------------+ | Table H1 | +-------------+------------------+ | Table H2a | Table H2b | +=============+==================+ | a1 | b1 | +------ ...

Inserting multiple rows of data into a MySQL database in a single page using only one query in PHP

This snippet shows a MySQL query being used to update and insert data into a database: if ($_POST["ok"] == "OK") { $updateSQL = sprintf("UPDATE attend SET at_status=%s, at_remarks=%s WHERE at_tt_idx=%s", GetSQLValueString ...

One effective way to transfer state to a child component using function-based React

My goal is to pass an uploaded file to a child component in React. Both the parent and child components are function-based and utilize TypeScript and Material-UI. In the Parent component: import React from 'react'; import Child from './ ...

Simplified JavaScript Object Structure

A JSON array that is flat in structure looks like this: var flatObject = [ { id : "1", parentId : "0", name : "object 1" }, { id : "2", parentId : "1", name : "object 2" }, { id : "3", parentId : "2", name : "object 3" }, { id : "4", pare ...

Having trouble creating a polygon from JSON in ESRI ArcGIS Javascript framework?

Can anyone assist with understanding the issue of trying to draw a polygon using the ESRI ArcGIS Javascript API? The image, JSON string, and code snippets provided below outline the code, console output, and expected behavior. Any help would be greatly app ...

I am encountering difficulties adding an array to Firebase due to the lack of asynchronous nature in Node.js

As a beginner in the world of nodejs, angularjs and firebase, I am encountering issues related to the asynchronous nature of nodejs while trying to load data into firebase. My goal is to search an existing list in firebase, add a new element to it, and wri ...

How can we cycle through multiple colors using lerp in Three.js?

I am currently engaged in a project using the Three.JS Online Editor. The main goal of my project is to create a Day/Night Cycle that loops through various colors to set the scene background. The cycle should include: Day Sunrise/Sunset Night Sunrise/Suns ...

"Trouble with props: List items not showing up after refreshing the page

I am facing an issue with my "Event Selector" component where it is not displaying the list items as expected. The component is supposed to create a button for each item in the 'lists' passed via props. Strangely, the items do not show up upon re ...

Unable to alter state from the onClick event of a dialog button

In the process of developing a Next.js app, I encountered an interesting challenge within one of the components involving a DropdownMenu that triggers a DialogAlert (both powered by Shadcn components). The issue arises when attempting to manage the dialog& ...

Changing the text alignment to justify in OWA - HTML emails

Having trouble navigating the Outlook Web App (OWA)? It seems like there are countless issues with different Outlook clients, but OWA is definitely the most poorly documented one. The snippet of code below functions flawlessly in all email clients such as ...

What could be causing my page to suddenly disappear?

After saving my changes in the IDE and refreshing the browser to test the prompt() function in my index.js file, the entire page goes blank, showing only a white screen. I double-checked the syntax of my function and it seems correct. Everything else on th ...