Why am I getting “undefined” when I try to retrieve this array of objects from firebase?

旧城冷巷雨未停 提交于 2021-02-11 12:19:05

问题


I'm building this exercise which involves the user filling out a form, and the info from the form is pushed into a firebase database and it produces a card which contains the info.

There are basically three functions: addBookToLibrary() which takes the info from the form after the user hits the submit button and puts it into firebase, render() which draws the card with the info on it, and Book which creates the object from the data entered into the form.

I decided to add retrievefromDatabase() which would pull from the firebase database every time the page is loaded, and that's where I'm running into trouble.

I have one code that works, but it's a little complicated because it basically replicates render() and makes two calls on firebase. A firebase pro here at StackOverflow suggested a new retrievefromDatabase() and it's a lot cleaner and only makes one call but it causes the card to show all fields as "undefined."

I poked around by inserting "console.log" and each part results in what one might expect: newPostKey is recognized, and so is oldBook and so is archiveBook.

Can someone wiser than me take a look and help me understand what the issue is?


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;
};

// better but not working:
// function retrievefromDatabase() {
//   firebase.database().ref("Book").once("value", (book) => {
//       book.forEach((snapshot) => {
//           newPostKey = snapshot.key;
//           console.log(newPostKey)

//           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;
//           };
//           console.log(oldBook)
//           var archiveBook = new oldBook(snapshot.val().title,
//               snapshot.val().fname,
//               snapshot.val().lname,
//               snapshot.val().pubDate,
//               snapshot.val().contrib,
//               snapshot.val().own);
//               console.log(archiveBook);
//       })
//       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);
      });
    };
  };
};

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);
  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.once('value', function(snapshot) {
  titlesnap = snapshot.val();
  });
// why is this reversed? variable precedes

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

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

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

  let contribRef = firebase.database().ref('Book/' + newPostKey + '/contrib');
  contribRef.once('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;
}

if you want to see it in action, it's here: https://library-firebase.acchang.repl.co/

来源:https://stackoverflow.com/questions/63321366/why-am-i-getting-undefined-when-i-try-to-retrieve-this-array-of-objects-from-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!