PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Saturday, October 15, 2022

[FIXED] How to get an element inside a function javascript

 October 15, 2022     dom, function, html, javascript     No comments   

Issue

I'm trying to use the value that each book has on its "status" and make the function "changeStatus()" run but "book.status" is defined inside a function, how can I get it? or is there any other way i can change the button behavior on click? I tried using a querySelector but it only allows me to click one button per refresh

let books = [];

const $name = document.querySelector("#name");
const $author = document.querySelector("#author");
const $status = document.querySelector("#status");
const $pages = document.querySelector("#pages"); 
const $tableBody = document.querySelector("#book-table-body");


function addBookToTable() {
    // checkLocalStorage();
    $tableBody.innerHTML = "";
    books.forEach((book) => {
      const htmlBook = `
        <tr>
          <td>${book.title}</td>
          <td>${book.author}</td>
          <td>${book.pages}</td>
          <td><button class="status-button" onclick="changeStatus()">${book.status}</button></td>
          <td><button class="delete">delete</button></td>
        </tr>
        `;
      $tableBody.insertAdjacentHTML("afterbegin", htmlBook);
    });
  }

 function changeStatus(){
   
 }

const addBook = (event) => {
    event.preventDefault();
    let book = {
        title: $("#title").val(),
        author: $("#author").val(),
        pages: $("#pages").val(),
        status: $("#status").val(),
    };
    const cb = document.querySelector("#status");

    if (cb.checked === true) {
        book.status = "read";
    } else {
        book.status = "not read";

    }

    books.push(book);

    document.forms[0].reset();
    // Update DOM
    addBookToTable(book);

    const deleteBtn = document.querySelector(".delete");
    deleteBtn.addEventListener("click", function deleteBook(){
        books.splice(books.indexOf(book), 1);
        addBookToTable(book);
    })

    // const myBtn = document.querySelector(".status-button");
    // myBtn.addEventListener('click', function changeStatus(){
    //     if (book.status === "read"){
    //         myBtn.innerHTML="not read"
    //         book.status = "not read"
    //     } 
    //     else if(book.status === "not read"){
    //         myBtn.innerHTML = "read";
    //         book.status = "read"
    //     }
    // }
    // );


    localStorage.setItem("myMangaList", JSON.stringify(books));
};

function popForm() {
    $("#popup").removeClass("hide");
}

function minimizeForm(){
    $("#popup").addClass("hide");
}

function hideForm() {
    $("#popup").addClass("hide");
    $("#main-page").removeClass("hide");
}

function toggle() {
    $("#main-page").addClass("hide");

}
* {
  font-family: 'Lato', sans-serif;
  text-align: center;
  /* background-image: url(./images/image.jpg);
  background-position: bottom;
  background-size: cover; */
}

.hide {
  display: none;
}

.hide-form {
  background-color: transparent;
  color: white;
  border: none;
  cursor: pointer;
  font-size: 1.5rem;
  margin-top: 20px;
  margin-right: 15px;
  position: absolute;
  top: 0;
  right: 0;
}

h1 {
  font-size: 2.5rem;
  font-weight: 900;
  font-family: 'Work Sans', sans-serif;
}

h1 span {
  color: #48abe0;
}

table {
  border-collapse: collapse;
  width: 100%;
}

td,
th {
  /* border: 1px solid #dddddd; */
  text-align: center;
  padding: 8px;
}


#main-page {
  margin-right: 80px;
  margin-left: 80px;

}

#addBook {
  border-radius: 70%;
  background-color: #48abe0;
  color: white;
  border: none;
  padding: 5px;
  font-size: 31px;
  height: 65px;
  width: 65px;
  box-shadow: 0 2px 4px darkslategray;
  cursor: pointer;
  transition: all 0.2s ease;
  position: fixed;
  bottom: 25px;
  right: 25px;
}


#popup {
  /* display: flex; */
  justify-content: center;
  align-items: center;
  flex-direction: column;
  gap: 30px;
  padding-top: 50px;
  padding-bottom: 50px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 300px;
  background: #48abe0;
  border-radius: 10px;
}

#popup input {
  width: 80%;
  padding: 15px;
  margin-top: 25px;
  border: 1px solid;
  border-radius: 5px;
  outline: none;
  color: white;
  font-weight: bold;
  font-size: 1em;
  background: #48abe0;

}

.status-box {
  margin-top: 25px;
}
<!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">

    <!-- Stylesheet -->
    <link rel="stylesheet" href="style.css">

    <!-- fonts -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link
        href="https://fonts.googleapis.com/css2?family=Edu+NSW+ACT+Foundation:wght@500&family=Edu+QLD+Beginner:wght@400;600;700&family=Edu+TAS+Beginner:wght@700&family=Josefin+Sans:wght@300&family=Lato&family=Montserrat:wght@100;600&family=Mouse+Memoirs&family=Poppins:ital,wght@0,500;1,200&family=Quicksand:wght@300&family=Ubuntu:wght@300&family=Work+Sans:wght@200&display=swap"
        rel="stylesheet">

    <title>Library</title>
</head>

<body>
    <h1>My <span>Manga</span> Library</h1>

    <div id="popup" class="hide">
        <form>
            <button class="hide-form" onclick=" minimizeForm()">X</button>
            <!-- <label for="title">Manga Title:</label> -->
            <input type="text" id="title" placeholder="Title eg: One Piece"> <br>

            <!-- <label for="author">Author:</label> -->
            <input type="text" id="author" placeholder="Author eg: Eichiro Oda"><br>

            <!-- <label for="pages">Pages:</label> -->
            <input type="text" id="pages" placeholder="Pages eg: 2000"><br>

            <div class="status-box">
                <label for="status">Read the book</label>
                <input type="checkbox" id="status" name="status" value="">

            </div>


            <button type="submit" id="submit" onclick="addBook(event); hideForm()">Submit</button>

        </form>
    </div>


    <!-- onclick="addBook() -->
    <div id="main-page">
        <h1>list</h1>
        <div id="books-grid">
            <table id="di-books">
                <tr>
                    <th>Name</th>
                    <th>Author</th>
                    <th>Pages</th>
                    <th>Status</th>
                    <th></th>
                </tr>
                <tbody id="book-table-body"></tbody>
            </table>
        </div>

        <button id="addBook" onclick="popForm(); toggle()">+</button>

    </div>

    <!-- JQuery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="app.js"></script>
</body>

</html>


Solution

If you want to update the status of a book, you need a way to identify each book uniquely. Although it is possible to do this based on e.g. title or author, the reality is that those fields are not guaranteed to be unique.

Typically, you'd use the Id number of a database entry, but since you're using mock data that isn't realy an option here. We could e.g. use a UUID though:

    let book = {
        title: $("#title").val(),
        author: $("#author").val(),
        pages: $("#pages").val(),
        status: $("#status").val(),
        id: self.crypto.randomUUID() //Warning: might only work with HTTPS sites. Implement your own unique id in any way you please.
    };

Now we have a unique id, we can use it to couple each status button with a unique book entry. Lets adjust the HTML:

 const htmlBook = `
        <tr>
          <td>${book.title}</td>
          <td>${book.author}</td>
          <td>${book.pages}</td>
          <td><button class="status-button" onclick="changeStatus('${book.id}')">${book.status}</button></td>
          <td><button class="delete">delete</button></td>
        </tr>
        `;

and lets write the update function:

 function changeStatus(id){
        //step 1: find our book with the matching unique id
        let book = books.filter(book => book.id === id)[0];
         //Step 2: update the book its status
         if (book.status === "read"){
             book.status = "not read";
         } 
         else if(book.status === "not read"){
             book.status = "read"
         }
   //Step 3: update our table with the new data.
   addBookToTable();
     };

And voila, we're able to switch the status of any book!

I tried to stick as close to your code as possible so you'd better understand it, but a lot more improvements can be implemented, such as event listeners instead of explicitly calling the changeStatus function, but I'll leave that as an exercise to you.

Full working example: codepen



Answered By - Jeroen Verfaillie
Answer Checked By - Cary Denson (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing