show data pulled from localStorage

I'm struggling to figure out how to use localStorage for the first time, specifically in storing an array of objects and displaying that information even after page refresh. Currently, I can see that it is being stored but not displayed.

const bookList = document.querySelector(".booklist");
const bookCards = document.querySelector(".booklist__books");
let library = JSON.parse(localStorage.getItem("library") ?? "[]");

// ---------------------- Book Constructor -------------------------------
class Book {
  constructor(title, author, pages, status) {
    this.title = title;
    this.author = author;
    this.pages = pages;
    this.status = status;
  }
}

// ---------------------- Add a new book to list -------------------------------

bookList.addEventListener("submit", (event) => {
  event.preventDefault();

  const title = document.getElementById("new-book").value.trim();
  const author = document.getElementById("author").value.trim();
  const pages = document.getElementById("pages").value.trim();
  const status = "Unread";

  if (!title) return;
  if (!author) return;
  if (!pages) return;

  const book = new Book(title, author, pages, status);

  library.push(book);

  const bookElement = document.createElement("li");
  const bookCollection = bookList.querySelector(".booklist__books");
  bookElement._book = book;

  library.forEach((book) => {
    bookElement.classList.add("book");
    bookElement.innerHTML = DOMPurify.sanitize(` <span class="book__info"
      ><span class="title_info">${title}</span> ⏤ <span class="author_info">${author}</span> ⏤ <span class="pages_info">${pages} Pages</span></span
    >
    <button class="book__read-button">Unread</button>
    <button type="button" class="book__delete-button">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="192"
        height="192"
        fill="#fff"
        viewBox="0 0 256 256"
      >
        <rect width="256" height="256" fill="none"></rect>
        <line
          x1="200"
          y1="56"
          x2="56"
          y2="200"
          stroke="#fff"
          stroke-linecap="round"
          stroke-linejoin="round"
          stroke-width="30"
        ></line>
        <line
          x1="200"
          y1="200"
          x2="56"
          y2="56"
          stroke="#fff"
          stroke-linecap="round"
          stroke-linejoin="round"
          stroke-width="30"
        ></line>
      </svg>
    </button>`);
    bookCollection.appendChild(bookElement);

    clearInputs();
    document.getElementById("new-book").focus();
    localStorage.setItem("library", JSON.stringify(library));
  });
});

function clearInputs() {
  document.querySelector("#new-book").value = "";
  document.querySelector("#author").value = "";
  document.querySelector("#pages").value = "";
}

//-------------------Toggle Read or Unread Button --------------------------

bookList.addEventListener("click", (e) => bookEdit(e));

function bookEdit(event) {
  if (event.target.classList.contains("book__read-button")) {
    console.log(event.target);
    event.target.classList.toggle("clicked");
    event.target.textContent =
      event.target.textContent == "Unread" ? "Read" : "Unread";
    //update object
    if (event.target.parentNode._book)
      event.target.parentNode._book.status = event.target.textContent;
    console.log(library);
  }
  //-------------------Deleting Books --------------------------

  if (event.target.matches(".book__delete-button")) {
    const bookElement = event.target.parentElement;
    bookCards.removeChild(bookElement);
    const position = library.indexOf(event.target.parentNode._book);
    library.splice(position, 1);
    localStorage.setItem("library", JSON.stringify(library));

    if (bookCards.children.length === 0) {
      bookCards.innerHTML = "";
    }

    console.log(library);
  }
}
<!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="https://fonts.googleapis.com/css?family=Roboto:300,400,700"
    />

    <link rel="stylesheet" href="styles.css" />
    <title>Book Library</title>
  </head>
  <body>
    <main>
      <div class="top">
        <img src="img/Open Book.png" alt="open book icon" />
        <h2>Book Library</h2>
      </div>

      <form action="#" class="booklist" autocomplete="off">
        <div class="booklist__new-book">
          <div class="new-book__input-group">
            <label for="new-book">Add a Book</label>
            <input
              type="text"
              id="new-book"
              name="new-book"
              placeholder="Book name"
            />
            <input type="text" id="author" name="author" placeholder="Author" />
            <input
              type="number"
              id="pages"
              name="pages"
              placeholder="Number of Pages"
            />
          </div>

          <button type="submit" id="submit">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="192"
              height="192"
              fill="#000000"
              viewBox="0 0 256 256"
            >
              <rect width="256" height="256" fill="none"></rect>
              <line
                x1="40"
                y1="128"
                x2="216"
                y2="128"
                fill="none"
                stroke="#000000"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="30"
              ></line>
              <line
                x1="128"
                y1="40"
                x2="128"
                y2="216"
                fill="none"
                stroke="#000000"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="30"
              ></line>
            </svg>
            <span>Add Book</span>
          </button>
        </div>

        <!-- List of Books -->
        <ul class="booklist__books">
          <li class="book">
            <span class="book__info"
              ><span class="title_info">The Catcher in the Rye</span> ⏤
              <span class="author_info">J. D. Salinger</span> ⏤
              <span class="pages_info">277 Pages</span></span
            >
            <button class="book__read-button">Unread</button>
            <button type="button" class="book__delete-button">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="192"
                height="192"
                fill="#fff"
                viewBox="0 0 256 256"
              >
                <rect width="256" height="256" fill="none"></rect>
                <line
                  x1="200"
                  y1="56"
                  x2="56"
                  y2="200"
                  stroke="#fff"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="30"
                ></line>
                <line
                  x1="200"
                  y1="200"
                  x2="56"
                  y2="56"
                  stroke="#fff"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="30"
                ></line>
              </svg>
            </button>
          </li>
        </ul>
        <div class="booklist__empty-state">
          Your Book Library is empty, add some more books!📚
        </div>
      </form>
    </main>
    <!-- Adds DOMPurify library -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/1.0.7/purify.min.js"></script>

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

Appreciate your help!

Answer №1

Your code appears to be functioning correctly

Below is an updated version that can be executed here on Stack Overflow using a try statement

const saveLibrary = () => {
  try {
    localStorage.setItem("library", JSON.stringify(library));
  } catch {
    console.log("Would have set it here", library)
  }
}
const bookList = document.querySelector(".booklist");
const bookCards = document.querySelector(".booklist__books");
let library = []
try {
  library = JSON.parse(localStorage.getItem("library") ?? "[]" );
} catch {}

// ---------------------- Book Constructor -------------------------------
class Book {
  constructor(title, author, pages, status) {
    this.title = title;
    this.author = author;
    this.pages = pages;
    this.status = status;
  }
}

// ---------------------- Add a new book to list -------------------------------

bookList.addEventListener("submit", (event) => {
  event.preventDefault();

  const title = document.getElementById("new-book").value.trim();
  const author = document.getElementById("author").value.trim();
  const pages = document.getElementById("pages").value.trim();
  const status = "Unread";

  if (!title) return;
  if (!author) return;
  if (!pages) return;

  const book = new Book(title, author, pages, status);

  library.push(book);

  const bookElement = document.createElement("li");
  const bookCollection = bookList.querySelector(".booklist__books");
  bookElement._book = book;

  library.forEach((book) => {
    bookElement.classList.add("book");
    bookElement.innerHTML = DOMPurify.sanitize(` <span class="book__info"
      ><span class="title_info">${title}</span> ⏤ <span class="author_info">${author}</span> ⏤ <span class="pages_info">${pages} Pages</span></span
    >
    <button class="book__read-button">Unread</button>
    <button type="button" class="book__delete-button">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="192"
        height="192"
        fill="#fff"
        viewBox="0 0 256 256"
      >
        <rect width="256" height="256" fill="none"></rect>
        <line
          x1="200"
          y1="56"
          x2="56"
          y2="200"
          stroke="#fff"
          stroke-linecap="round"
          stroke-linejoin="round"
          stroke-width="30"
        ></line>
        <line
          x1="200"
          y1="200"
          x2="56"
          y2="56"
          stroke="#fff"
          stroke-linecap="round"
          stroke-linejoin="round"
          stroke-width="30"
        ></line>
      </svg>
    </button>`);
    bookCollection.appendChild(bookElement);

    clearInputs();
    document.getElementById("new-book").focus();
    saveLibrary();
  });
});

function clearInputs() {
  document.querySelector("#new-book").value = "";
  document.querySelector("#author").value = "";
  document.querySelector("#pages").value = "";
}

//-------------------Toggle Read or Unread Button --------------------------

bookList.addEventListener("click", (e) => bookEdit(e));

function bookEdit(event) {
  if (event.target.classList.contains("book__read-button")) {
    console.log(event.target);
    event.target.classList.toggle("clicked");
    event.target.textContent =
      event.target.textContent == "Unread" ? "Read" : "Unread";
    //update object
    if (event.target.parentNode._book)
      event.target.parentNode._book.status = event.target.textContent;
    console.log(library);
  }
  //-------------------Deleting Books --------------------------

  if (event.target.matches(".book__delete-button")) {
    const bookElement = event.target.parentElement;
    bookCards.removeChild(bookElement);
    const position = library.indexOf(event.target.parentNode._book);
    library.splice(position, 1);
    if (bookCards.children.length === 0) {
      bookCards.innerHTML = "";
    }
    saveLibrary()
  }
}
<!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="https://fonts.googleapis.com/css?family=Roboto:300,400,700" />

  <link rel="stylesheet" href="styles.css" />
  <title>Book Library</title>
</head>

<body>
  <main>
    <div class="top">
      <img src="img/Open Book.png" alt="open book icon" />
      <h2>Book Library</h2>
    </div>

    <form action="#" class="booklist" autocomplete="off">
      <div class="booklist__new-book">
        <div class="new-book__input-group">
          <label for="new-book">Add a Book</label>
          <input type="text" id="new-book" name="new-book" placeholder="Book name" />
          <input type="text" id="author" name="author" placeholder="Author" />
          <input type="number" id="pages" name="pages" placeholder="Number of Pages" />
        </div>

        <button type="submit" id="submit">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="192"
              height="192"
              fill="#000000"
              viewBox="0 0 256 256"
            >
              <rect width="256" height="256" fill="none"></rect>
              <line
                x1="40"
                y1="128"
                x2="216"
                y2="128"
                fill="none"
                stroke="#000000"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="30"
              ></line>
              <line
                x1="128"
                y1="40"
                x2="128"
                y2="216"
                fill="none"
                stroke="#000000"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="30"
              ></line>
            </svg>
            <span>Add Book</span>
          </button>
      </div>

      <!-- List of Books -->
      <ul class="booklist__books">
        <li class="book">
          <span class="book__info"><span class="title_info">The Catcher in the Rye</span> ⏤
          <span class="author_info">J. D. Salinger</span> ⏤
          <span class="pages_info">277 Pages</span></span>
          <button class="book__read-button">Unread</button>
          <button type="button" class="book__delete-button">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="192"
                height="192"
                fill="#fff"
                viewBox="0 0 256 256"
              >
                <rect width="256" height="256" fill="none"></rect>
                <line
                  x1="200"
                  y1="56"
                  x2="56"
                  y2="200"
                  stroke="#fff"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="30"
                ></line>
                <line
                  x1="200"
                  y1="200"
                  x2="56"
                  y2="56"
                  stroke="#fff"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="30"
                ></line>
              </svg>
            </button>
        </li>
      </ul>
      <div class="booklist__empty-state">
        Your Book Library is empty, add some more books!📚
      </div>
    </form>
  </main>
  <!-- Adds DOMPurify library -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/1.0.7/purify.min.js"></script>

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

</html>

Answer №2

If you want to retrieve an item from your local storage, you can do so by using the following code snippet:

localStorage.getItem("library");

Once you have retrieved the item, you can parse the JSON string like this:

let library  = localStorage.getItem("library");
if(library){
   library = JSON.parse(library); //convert JSON string to array
   console.log(library); //you can now use the array however you wish
} else{
     library = [];
}

}

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

Using Javascript to delete a cookie that was created by an AJAX response

Within my Webapp (which is currently running at localhost/myApp/), I am utilizing an ajax call as shown below: $.ajax({ type: "GET", url: "http://localhost:8080/my.module/Login/login?user=abc&password=123", xhrFields: { withCredent ...

Tips for repairing a button using a JavaScript function in an HTML document

I am currently working on extracting titles from body text. To achieve this, I have created a button and linked my function to it. The issue I am facing is that when I click on the button, it disappears from its original position. I intend to keep it in pl ...

Is it possible to incorporate vector graphics/icons by simply adding a class to a span element in HTML5?

In order to add a glyphicon icon to our webpage, we simply need to include its class within a span element, as demonstrated here: <span class="glyphicon glyphicon-search"></span> We also have a few files in .ai format that can be converted to ...

Which is the better option for selecting DOM elements in a Vuejs 3 application: using raw js or jquery?

 I am currently working on developing an application using Node.js and Vue.js 3. One of the features I have implemented is a sidebar that dynamically fetches links from a routes file and displays them. The sidebar consists of a component that organize ...

Incorporate data from a CSV file into an HTML table on the fly with JavaScript/jQuery

I have a CSV file that is generated dynamically by another vendor and I need to display it in an HTML table on my website. The challenge is that I must manipulate the data from the CSV to show corrected values in the table, only displaying products and not ...

Tips for controlling the upload of a .exe.png file or converting a .exe file to a png file for uploading in angular 8

I had originally set up restrictions to only allow image file types such as JPG, JPEG, PNG, and TIFF. However, I discovered that users were able to upload .exe files simply by renaming them. For example, changing dell.exe.png or dell.exe to dell.png allo ...

The virtual method 'android.location.Location' was called in error

I'm using WL.Device.Geo.acquirePosition(onGeoLocationSuccess, onGeoLocationFailure, options) from MobileFirst to retrieve a device's location. Initially, everything works smoothly as I successfully obtain the location. However, after clearing t ...

Find the nearest element with a specific class using jQuery

I am currently using jQuery version 1.12.4 for the purpose of retrieving the value from the closest element with a specific class selector. Unfortunately, I am encountering difficulty in selecting the closest element as desired. $(function() { $("[cla ...

Angular 8 fails to retain data upon page refresh

I have a property called "isAdmin" which is a boolean. It determines whether the user is logged in as an admin or a regular user. I'm using .net core 2.2 for the backend and Postgre for the database. Everything works fine, but when I refresh the page, ...

call a custom form submission using jquery first, followed by a regular form submission

Is it possible to attach a submit() handler to a form in order to execute an ajax request, and then have the form submit itself normally once the request is complete? Using $('#myForm').submit() seems to just result in the same function being cal ...

How about this: "Looking to Share on Social Media with ME

After developing an app using MEAN.js, I made enhancements to the Articles (blog) section to improve SEO, readability, and design. However, one issue I'm struggling with is how to properly share these Articles on social media platforms like Facebook, ...

Using Jquery to automatically populate an input field if the user already exists

I'm currently working on populating a form if the user input for name and firstname already exists in my database. However, I am facing an issue with my JavaScript program where it fails to check if the name and firstname combination already exists i ...

How can I select the specific element within a class when a particular checkbox is selected?

Having a dynamically generated list of elements, each structured like this: <div class="under-item-description"> <span class="under-compare-price">100</span><span class="under-price">50</span> <span class="under-compar ...

How can I prevent my mouse click from being overridden by my mouse hover?

Currently, I am developing a Sudoku game using JavaScript and facing some challenges with mouse events. My goal is to enable users to hover over a square and have it change color, as well as click on a square to highlight the entire row, column, and quadra ...

Is there a way to send arguments to a pre-existing Vue JS application?

A Vue application we've developed connects to a Web Service to retrieve data. However, the URL of the web service varies depending on the installation location of the app. Initially, we considered using .env files for configuration, but realized that ...

Is it possible for Nextjs routing catchAll to coexist with a slug folder within a route?

When converting my pages to ISR, I encountered an issue with handling params and dynamic routes. One example is where article/?pageNumber=2 needs to be rewritten as article/2 in middleware for improved performance. However, this change in routing structure ...

Is it recommended to rely on Javascript for altering the content of a div across an entire website?

I am in the process of creating my personal portfolio and have a few inquiries regarding the framework to implement. Currently, I have an index.html page that contains all the information I want displayed when visitors land on the site. Additionally, ther ...

Retrieve the IDs of list elements in order to dynamically update a div using AJAX

I'm facing a bit of a challenge at the moment. I have a webpage that uses jQuery to load three different views: one displaying all categories associated with the user, another showing the image and name of items within the selected category, and a thi ...

Retrieving information in Ionic

Having trouble fetching data from a server in my first ionic application. I keep getting an error that says "Cannot read Property" while trying to attach my code snippet. Here is what my code looks like: import { Component } from '@angular/core' ...

Troubleshooting the "Request failed with status code 500" error when refreshing a page in a React application

Every time the page is reloaded, an error message pops up saying: Uncaught (in promise) Error: Request failed with status code 500. Here's the code in list.tsx: const [state, setState] = useState([]); const { getRoom } = useRoom(); const fe ...