首页 > 解决方案 > 检索firebase对象以绘制带有复选框的卡片,但每次复选框更改时都会绘制一张新卡片

问题描述

为了学习对象,我构建了这个图书馆应用程序,您可以在表格中输入您最喜欢的书名和作者的名字,它会生成一张包含该信息的卡片。

表单上有一个复选框来标记您是否拥有它和一个“删除”按钮。

它与一个addtoLibrary()函数一起工作,该函数从表单中获取信息,将其放入一个对象中,然后将该对象放入 firebase。

在该函数中,我有另一个函数调用render(),它从 firebase 获取信息并将其放入 DOM。

接下来,我让应用程序在每次打开应用程序时都在 DOM 上绘图,以便它显示所有以前的条目。

因此,我构建了另一个名为的函数,该函数retrievefromDatabase()也包含该render()函数,并循环遍历对象列表以重绘它们。

不过,我现在面临的问题是,无论何时选中或取消选中复选框,该retrievefromDatabase()功能都会激活并抽出另一张牌。

我的“删除”按钮遇到了这个问题,它也改变了firebase的状态并绘制了一张新卡。为了解决这个问题,我将 firebase 上的一个调用从.onto更改为.once有帮助。

但是“删除”按钮很简单,因为你不能不断地来回改变它的状态。

我只能retrievefromDatabase()运行一次,但是如果另一个用户添加了一张卡片,它就不会动态更新。但它会在重新加载时显示,我可以忍受。

retrievefromDatabase()如果像这样工作会更好addtoLibrary(),我可以点击复选框让我高兴,因为它不是从 firebase 读取,只是将更改写入它。

因此,只有当它们开始在数据库中时才会绘制新卡。提交的任何新卡都不存在此问题。

所以我认为我的障碍是我没有很好地管理火力基地。我花了一周的时间试图了解如何进行 CRUD,所以显然我不是专业人士!

你能提出一个解决方案吗?

let newPostKey;
let titlesnap;
let fnamesnap;
let lnamesnap;
let pubsnap;
let contribsnap;

function Book(title, fname, lname, pubDate, contrib, own) {
  this.title = title;
  this.fname = fname;
  this.lname = lname;
  this.pubDate = pubDate;
  this.contrib = contrib;
  this.own = own;
};

function retrievefromDatabase() {
  firebase.database().ref("Book").once("value", gotData);
      function gotData(Book) {
      var books = Book.val();
      var keys = Object.keys(books);
        for (var i = 0; i < keys.length; i++) {
          firebase.database().ref("Book/" + keys[i]).on("value", function(snapshot) {
          newPostKey = snapshot.key;    
          function oldBook(title, fname, lname, pubDate, contrib, own) {
            this.title = title;
            this.fname = fname;
            this.lname = lname;
            this.pubDate = pubDate;
            this.contrib = contrib;
            this.own = own;
          };          
          var addBook = new oldBook(snapshot.val().title, 
          snapshot.val().fname, 
          snapshot.val().lname, 
          snapshot.val().pubDate,
          snapshot.val().contrib,
          snapshot.val().own);
          render(oldBook);
        })}}};

retrievefromDatabase();

const submitButton = document.querySelector(".submitButton")
submitButton.addEventListener("click", e => {
  // the prevents the field from clearing on submit
  e.preventDefault();
  addBookToLibrary();
  })

function addBookToLibrary() {
  let title = document.querySelector("#title").value;
  let fname = document.querySelector("#fname").value;
  let lname = document.querySelector("#lname").value;
  let pubDate = document.querySelector("#pubDate").value;
  let contrib = document.querySelector("#contrib").value;
  let own = document.querySelector("#own").checked;
  var addBook = new Book(title, fname, lname, pubDate, contrib, own);
  // I could just put document.querySelector values into var addBook but this is clearer
  newPostKey = firebase.database().ref().child('Book').push().key;
  firebase.database().ref().child('Book').child(newPostKey).set(addBook);
  // console.log(newPostKey);
  // myLibrary.push(addBook);
  render();
  document.querySelector("#title").value = "";
  document.querySelector("#fname").value = "";
  document.querySelector("#lname").value = "";
  document.querySelector("#pubDate").value = "";
  document.querySelector("#contrib").value = "";
  document.querySelector("#own").checked = false;
  // I can also shorten this with form.reset()
  // https://discord.com/channels/505093832157691914/690590001486102589/736653879684628491
};

function render() {
  const bookContainer = document.createElement("div");
  bookContainer.classList.add("book-container");

  const newVolume = document.createElement("div");
  newVolume.classList.add("volume");
  bookContainer.appendChild(newVolume);
  bookContainer.setAttribute('id', `${newPostKey}`);

  const frontCover = document.createElement("div");
  newVolume.appendChild(frontCover);
 
  frontCover.style.setProperty("background-color", getRandomColor());
  
  let TitleRef = firebase.database().ref('Book/' + newPostKey + '/title');
  TitleRef.on('value', function(snapshot) {
  titlesnap = snapshot.val();
  });
// why is this reversed? variable precedes

  let FnameRef = firebase.database().ref('Book/' + newPostKey + '/fname');
  FnameRef.on('value', function(snapshot) {
  fnamesnap = snapshot.val();
  });

  let LnameRef = firebase.database().ref('Book/' + newPostKey + '/lname');
  LnameRef.on('value', function(snapshot) {
  lnamesnap = snapshot.val();
  });

  let pubRef = firebase.database().ref('Book/' + newPostKey + '/pubDate');
  pubRef.on('value', function(snapshot) {
  pubsnap = snapshot.val();
  });

  let contribRef = firebase.database().ref('Book/' + newPostKey + '/contrib');
  contribRef.on('value', function(snapshot) {
  contribsnap = snapshot.val();
  });

  frontCover.innerHTML = "<br /><br />"
                        + "<b>" + titlesnap + "</b>" + "<br /><br />" 
                        + fnamesnap + "&nbsp;"
                        + lnamesnap + "<br /><br />"
                        + "Published: " + pubsnap + "<br />"
                        + "Added by: <br />" + contribsnap + "<br />";
                        
// reads checkbox form, adds it to the rendered volume and interprets value given
  const checkbox = document.createElement('input'); 
  checkbox.type = "checkbox"; 
  checkbox.id = "checkbox"; 

if (document.getElementById("own").checked == true) {
  checkbox.checked = true;
}
else if (document.getElementById("own").checked == true) {
  checkbox.checked = false;
};  

checkbox.addEventListener("change", function() {
if (checkbox.checked === false) {
  firebase.database().ref('Book/' + bookContainer.id + '/own').set(false);
}
else if (checkbox.checked === true) {
  firebase.database().ref('Book/' + bookContainer.id + '/own').set(true);
    }
  });

const label = document.createElement("label"); 
label.appendChild(document.createTextNode(" I own a copy")); 
const newgraf = document.createElement("p")

frontCover.appendChild(checkbox);
frontCover.appendChild(label);
frontCover.appendChild(newgraf);

const removeButton = document.createElement('button')
frontCover.appendChild(removeButton);
removeButton.textContent = 'Remove';
removeButton.addEventListener("click", function(event){
    firebase.database().ref('Book/').child(bookContainer.id).remove()
    bookContainer.remove();
})

libraryContainer.insertAdjacentElement('afterbegin',bookContainer);
};

function getRandomColor() {
  color = "hsl(" + Math.random() * 360 + ", 100%, 20%)";
  return color;
}

如果您想看到它的实际效果:https ://project-library.acchang.repl.co/

标签: javascriptfirebasefirebase-realtime-databasecheckboxjavascript-objects

解决方案


明白了,我不得不重写retrievefromDatabase()没有render()

function retrievefromDatabase() {
firebase.database().ref("Book").once("value", gotData);
  function gotData(Book) {
    var books = Book.val();
    var keys = Object.keys(books);
  
    for (var i = 0; i < keys.length; i++) {

      firebase.database().ref("Book/" + keys[i]).once("value", function(snapshot) {  
      titlesnap = snapshot.val().title; 
      fnamesnap = snapshot.val().fname;
      lnamesnap = snapshot.val().lname;
      pubsnap = snapshot.val().pubDate;
      contribsnap = snapshot.val().contrib;
      newPostKey = snapshot.key;

      const bookContainer = document.createElement("div");
      bookContainer.classList.add("book-container");
      const newVolume = document.createElement("div");
      newVolume.classList.add("volume");
      bookContainer.appendChild(newVolume);
      bookContainer.setAttribute('id', `${newPostKey}`);
      const frontCover = document.createElement("div");
      newVolume.appendChild(frontCover);
      frontCover.style.setProperty("background-color", getRandomColor());

      frontCover.innerHTML = "<br /><br />"
      + "<b>" + titlesnap + "</b>" + "<br /><br />" 
      + fnamesnap + "&nbsp;"
      + lnamesnap + "<br /><br />"
      + "Published: " + pubsnap + "<br />"
      + "Added by: <br />" + contribsnap + "<br />";

      const checkbox = document.createElement('input'); 
      checkbox.type = "checkbox"; 
      checkbox.id = "checkbox"; 
    
      if (snapshot.val().own == true) {
        checkbox.checked = true;
      }
      else {
        checkbox.checked = false;
      };  
      
    checkbox.addEventListener("change", function() {
    if (checkbox.checked === false) {
      firebase.database().ref('Book/' + bookContainer.id + '/own').set(false);
    }
    else if (checkbox.checked === true) {
      firebase.database().ref('Book/' + bookContainer.id + '/own').set(true);
        }});

    const label = document.createElement("label"); 
    label.appendChild(document.createTextNode(" I own a copy")); 
    const newgraf = document.createElement("p")
    
    frontCover.appendChild(checkbox);
    frontCover.appendChild(label);
    frontCover.appendChild(newgraf);
    
    const removeButton = document.createElement('button')
    frontCover.appendChild(removeButton);
    removeButton.textContent = 'Remove';
    removeButton.addEventListener("click", function(event){
        firebase.database().ref('Book/').child(bookContainer.id).remove()
        bookContainer.remove();
    })

      libraryContainer.insertAdjacentElement('afterbegin',bookContainer);
      });
};
  };};

推荐阅读