0

I want a user to be able to put his info about their book and push it into the library. I can do this when it comes to display but I want to have it saved as a new object in javascript. A new array 'newBooks' that I created don't return a new value, it stays the same even though I used spread operator which is supposed to change the value. Could someone tell me what's going on?

const booksContainer = document.querySelector('.booksContainer');
const buttonNewBook = document.querySelector('.buttonNewBook');
const buttonConfirm = document.querySelector('.confirmBook')
const inputContainer = document.querySelector('.addNewBook');


buttonNewBook.addEventListener('click', () => {
  
  if (inputContainer.style.display === 'none') {
    inputContainer.style.display = 'flex'
  } else {
    inputContainer.style.display = 'none'
  } 
  
  if (buttonConfirm.style.display === 'none') {
    buttonConfirm.style.display = 'inline'
  } else {
    buttonConfirm.style.display = 'none'
  }
});




const books = [
{
  id: 1,
  imageUrl: '',
  title: 'Title:',
  author: 'Author:',
  pages: 'Pages:'
},
{
  id: 5, imageUrl: '',
  id: 6, title: 'Title:',
  id: 7, author: 'Author:',
  id: 8, pages: 'Pages:'
},
{
  id: 9, imageUrl: '',
  id: 10, title: 'Title:',
  id: 11, author: 'Author:',
  id: 12, pages: 'Pages:'
},
{
  id: 13, imageUrl: '',
  id: 14, title: 'Title:',
  id: 15, author: 'Author:',
  id: 16, pages: 'Pages:'
}
]


books.forEach((book, index) => {
let booksDisplay = document.createElement('div')
booksDisplay.setAttribute('class', 'booksDisplay')
booksContainer.appendChild(booksDisplay)

let booksDisplayImage = document.createElement('img');
    booksDisplayImage.src = (`${book.imageUrl}`)
    booksDisplayImage.setAttribute('class', 'booksImage');
    booksDisplay.appendChild(booksDisplayImage);

  let imageContainer = document.createElement('div')
    imageContainer.setAttribute('class', 'imageContainer');
    booksDisplay.appendChild(imageContainer);
    imageContainer.appendChild(booksDisplayImage)


  let booksDisplayTextTitle = document.createElement('p');
      booksDisplayTextTitle.setAttribute('class', 'titleText')

  let booksDisplayTextAuthor = document.createElement('p');
      booksDisplayTextAuthor.setAttribute('class', 'authorText')

  let booksDisplayTextPages = document.createElement('p');
      booksDisplayTextPages.setAttribute('class', 'pagesText')

  let booksDisplayTextDisplayTitle = document.createTextNode(`${book.title}`);
      booksDisplayTextTitle.appendChild(booksDisplayTextDisplayTitle);

  let booksDisplayTextDisplayAuthor = document.createTextNode(`${book.author}`);
      booksDisplayTextAuthor.appendChild(booksDisplayTextDisplayAuthor)

  let booksDisplayTextDisplayPages = document.createTextNode(`${book.pages}`);
      booksDisplayTextPages.appendChild(booksDisplayTextDisplayPages);

  let textContainer = document.createElement('div');
    textContainer.setAttribute('class', 'textContainer');
    booksDisplay.appendChild(textContainer);
    textContainer.appendChild(booksDisplayTextTitle);
    textContainer.appendChild(booksDisplayTextAuthor);
    textContainer.appendChild(booksDisplayTextPages);

    booksContainer.appendChild(booksDisplay);

    let buttonRead = document.createElement('button')


    let buttonRemove = document.createElement('button');
    buttonRemove.addEventListener('click', () => {
      booksDisplayTextTitle.textContent = 'Title:';
      booksDisplayTextAuthor.textContent = 'Author:';
      booksDisplayTextPages.textContent = 'Pages:';
      booksDisplayImage.style.display = 'none';
      imageContainer.style.border = '1px solid rgb(107, 107, 107)'
    });

    let buttonReadText = document.createTextNode ('I have read this book');
    let buttonRemoveText = document.createTextNode ('Remove a book');

    buttonRead.appendChild(buttonReadText);
    buttonRemove.appendChild(buttonRemoveText);
    textContainer.appendChild(buttonRead)
    textContainer.appendChild(buttonRemove)

   
});

const inputTitle = document.querySelector('#title');
const inputAuthor = document.querySelector('#author')
const inputPages = document.querySelector('#pages')
const inputImageUrl = document.querySelector('#imageUrl')
inputImageUrl.value = '';
inputTitle.value = '';
inputAuthor.value = '';
inputPages.value = '';


const titleText = document.querySelector('.titleText');
const authorText = document.querySelector('.authorText');
const pagesText = document.querySelector('.pagesText');
const bookImageUrl = document.querySelector('.booksImage');

console.log(inputTitle)





buttonConfirm.addEventListener('click', () => {
  bookImageUrl.src = inputImageUrl.value;
  titleText.textContent = 'Title:' + ' ' + inputTitle.value;
  authorText.textContent = 'Author:' + ' ' + inputAuthor.value;
  pagesText.textContent = 'Pages:' + ' ' + inputPages.value;
  const newBooks = books.map(newBook => {
    if (newBook.id == 1) {
      return {...newBook, author: inputAuthor.value, title: inputTitle.value, pages: inputPages.value}
    
    }
    return newBook;

  });
  console.log(newBooks)
});

console.log(books)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./styles/style.css">
    <title>Document</title>
</head>
<body>
<div class="myLibrary">
    
  <form class="addNewBook">
    <input type="text" name="titles" id="title" placeholder="Title">
    <input type="text" name="author" id="author" placeholder="Author">
    <input type="number" name="pages" id="pages" placeholder="Number of pages">
    <input type="link" name="imageUrl" id="imageUrl" placeholder="Image URL">
  </form>

  <div class="buttonContainer">
    <button class="buttonNewBook">Add a new book</button>
    <button class="confirmBook">Confirm</button>
  </div>

  <div class="booksContainer">
   
  </div>
    

    
    <script src="./scripts/script.js"></script>
</body>
</html>

1
  • 2
    Sorry, but why you declared books objects in that way? if you try to evaluate { id: 1, imageUrl: '', id: 2, title: 'Title:', id: 3, author: 'Author:', id: 4, pages: 'Pages:'} in browser console - you will see that the object will look like { "id": 4, "imageUrl": "", "title": "Title:", "author": "Author:", "pages": "Pages:"}. From your data - it is not possible for if expression newBook.id === 1 (or 2) to be true. Commented Jul 17, 2022 at 15:35

2 Answers 2

2

Your book is wrong formated

let info = {
  id: 1, imageUrl: '',
  id: 2, title: 'Title:',
  id: 3, author: 'Author:',
  id: 4, pages: 'Pages:'
}

console.log( info )

is the same as

let info = {}
info.id = 1
info.id = 2
info.id = 3
info.id = 4
info.title = .... 

there could be only one info.id propertie

I lost time understanding the purpose of your code, but I suggest you get inspired by this way of coding...

const
  newBookForm = document.forms['add-New-Book']
, books = 
    [ { id: 1, imageUrl: '', title: 'Title-1', author: 'Author:', pages: 'Pages:' } 
    , { id: 2, imageUrl: '', title: 'Title-2', author: 'Author:', pages: 'Pages:' } 
    , { id: 3, imageUrl: '', title: 'Title-3', author: 'Author:', pages: 'Pages:' } 
    , { id: 4, imageUrl: '', title: 'Title-4', author: 'Author:', pages: 'Pages:' } 
    ] 
, booksContainer = document.querySelector('.booksContainer')
, newBook = { id: books.reduce((r,{id})=>Math.max(r,id),0) }  
  ;

function displayNewBook(book)
  {
  let booksDisplay           = document.createElement('div')
      booksDisplay.className = 'booksDisplay'

  booksDisplay.innerHTML = `
  <div class="imageContainer">
    <img src="${book.imageUrl}" class="booksImage" >
  </div>
  <div class="textContainer">
    <p class"titleText">${book.title}</p>
    <p class"authorText">${book.author}</p>
    <p class"pagesText">${book.pages}</p>   
    <button data-op="readed" data-ref="${book.id}"> I have read this book</button>
    <button data-op="remove" data-ref="${book.id}"> Remove this book</button>
  </div>`

  booksContainer.appendChild(booksDisplay)
  }
books.forEach( displayNewBook )
  ;
newBookForm.onsubmit = e => e.preventDefault()  // disable form submit for no page relaoding
  ;
newBookForm.onclick = ({target: bt }) => 
  {
  if (!bt.matches('button')) return;

  let addBook = (bt.name==='btAdd')

  if ( addBook && !newBookForm.checkValidity() )
    {
    newBookForm.reportValidity()
    return
    }

  newBookForm.btAdd    .classList.toggle('noDisplay', addBook )
  newBookForm.btConfirm.classList.toggle('noDisplay', !addBook ) 
  newBookForm.btCancel .classList.toggle('noDisplay', !addBook ) 

  newBookForm.titles  .readOnly = addBook
  newBookForm.author  .readOnly = addBook
  newBookForm.pages   .readOnly = addBook
  newBookForm.imageUrl.readOnly = addBook

  if (bt.name==='btConfirm')
    {
    let book = 
      { id       : ++newBook.id
      , imageUrl : newBookForm.imageUrl.value
      , title    : newBookForm.titles.value
      , author   : newBookForm.author.value
      , pages    : newBookForm.pages.value 
      } 

    books.push( book )
    displayNewBook( book )

    newBookForm.reset()
    
    console.clear()
    console.log ( 'books:\n' + JSON.stringify(books).replaceAll('},{','}\n,{') ) 
    }
  }
booksContainer.onclick = ({target: target_Bt}) =>
  {
  if (!target_Bt.matches('button[data-op]')) return

  // console.clear()
  // console.log( target_Bt.dataset.op, target_Bt.dataset.ref )

  if (target_Bt.dataset.op==='readed')
    {
    // things to do with target_Bt.dataset.ref
    }
  if (target_Bt.dataset.op==='remove')
    {
    // things to do with target_Bt.dataset.ref

    // let idx = books.findIndex(({id})=>id=== +target_Bt.dataset.ref)

    target_Bt
      .closest('div.booksDisplay')
      .querySelector('div.imageContainer')
      .classList.add('BookRemove');
    }
  }
.booksContainer {
  font-family : Arial, Helvetica, sans-serif;
  font-size   : 14px;
  }
.imageContainer {
  width      : 80px;
  height     : 30px;
  background : aquamarine;
  }
.textContainer button {
  margin : 0 0 2.4em 1em;
  }
.imageContainer.BookRemove {
  border : 1px solid rgb(107, 107, 107);
  }
.noDisplay {
  display: none; 
  }
form[name="add-New-Book"]  {
  margin-bottom : 2em;
  width         : 20em;
  }
form input  {
  margin-bottom : .4em;
  width         : 19em;
  }
form fieldset  {
  padding-bottom : 0;
  margin-bottom  : .4em;
  }
form[name="add-New-Book"] input:read-only {
  background-color: lightblue;
  }
button[name="btConfirm"] {
  width            : 10em;
  background-color : #7bff00;
  border-radius    : 4px;
  }
button[name="btCancel"] {
  width            : 5em;
  background-color : #ebb222;
  border-radius    : 4px;
  }
.as-console-row::after {display: none !important;}
.as-console-row-code {background: yellow;}
<form name="add-New-Book">
  <fieldset>
    <legend> new Book </legend>
    <input type="text"   name="titles"   placeholder="Title"           required>
    <input type="text"   name="author"   placeholder="Author"          required>
    <input type="number" name="pages"    placeholder="Number of pages" required min="0">
    <input type="link"   name="imageUrl" placeholder="Image URL"       required>
  </fieldset>

  <button type="button" name="btAdd"> Add a new book </button>
  <button type="button" name="btConfirm" class="noDisplay"> Confirm </button>
  <button type="button" name="btCancel"  class="noDisplay"> Cancel </button>
  <button type="reset">reset</button>
</form>

<div class="booksContainer">

Sign up to request clarification or add additional context in comments.

6 Comments

What should I do then? Put every property into {} like this? {id: 1, imageUrl: ''}, {id: 2, title: 'Title:'}, {id: 3, author: 'Author:'}, {id: 4, pages: 'Pages:'}, The problem is that it creates new objects instead of properties.
I wanted a new array to be updated. When I asked a question, my new array was the same as the old array.
@madlib I added some improvement and a console.log(Books). I hope that this time it will calm your harsh demands and that you will at least be able to split a "thank you" ?
What do you mean by this way of coding? What's wrong with my coding? I do what's required in an odin project's task. Appreciate the code you've written, of course.
@madlib simple example of comparison, my function displayNewBook() is 19 lines long, your's is 65. I also use event delegation, etc.
|
0

Okay, I figured it out. It seems like I have to add an ID to the whole object(It was 4 before and I changed it to ID: 1. Then I added return {...newBook, author: inputAuthor.value, title: inputTitle.value, pages: inputPages.value} in a new array.

1 Comment

Yeah, I know. I'm gonna change that. I just wanted to share that I figured it out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.