I have a firebase database that looks like this:

Now, what I need is to retrieve every document inside 'canvas', including their name field. So, what I did is retrieving the document's name, and from that, I retrieve canvas documents of every single documents.
function getDatabase() {
let rowId = 0;
dbRef.get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// HTML for each row
let $idEmo = $("<th>", { "scope": "row" });
let $canvasEmo = $("<th>");
let $nameEmo = $("<th>");
let $dateEmo = $("<th>");
let $canvasEmoContent = $("<canvas>")
$canvasEmoContent.attr({
width: "100",
height: "100",
id: "db-canvas-" rowId
});
// Prepend data into one row
$idEmo.prepend(rowId);
$canvasEmo.prepend($canvasEmoContent);
$nameEmo.prepend(doc.data().name);
$dateEmo.prepend(doc.data().date);
let $tableRow = $("<tr>");
$tableRow.addClass("t-row");
$tableRow.prepend($idEmo, $canvasEmo, $nameEmo, $dateEmo);
$("#emoji-table-body").append($tableRow);
// Get the circles from the database in each row
let dbCircle = R.clone(circleTemplate);
dbRef.doc(doc.data().name).collection("canvas").get()
.then((querySnapshot) => {
querySnapshot.forEach((bit) => {
let i = 8 * bit.data().posY bit.data().posX;
dbCircle[i].posX = bit.data().posX;
dbCircle[i].posY = bit.data().posY;
dbCircle[i].isOn = bit.data().isOn;
dbCircle[i].color = bit.data().color;
});
})
.then(() => {
makeDatabaseCanvas("db-canvas-" rowId, dbCircle)
console.log(dbCircle)
console.log(dbCircle[3].isOn)
console.log(rowId)
rowId ;
})
});
});
}
Other functions:
function makeDatabaseCanvas(id, dCircle) {
renderBoard(id, 100);
for (let i = 0; i < 64; i ) {
renderCircle(id, dCircle[i].posX, dCircle[i].posY, dCircle[i].isOn, dCircle[i].color, 4);
}
}
function renderBoard(id, size) {
let context = document.getElementById(id).getContext('2d');
context.fillStyle = '#000000';
context.fillRect(0, 0, size, size);
}
// Circle rendering
function renderCircle(id, row, column, isOn, color, scale) {
let context = document.getElementById(id).getContext('2d');
let centerX = (row * 50 25) / scale;
let centerY = (column * 50 25) / scale;
let radius = 20 / scale;
context.beginPath();
context.arc(centerX, centerY, radius, 0, Math.PI * 2, true);
context.fillStyle = ((isOn) ? color : '#FFFFFF');
context.fill();
context.stroke();
}
The problem with this is: for the second Foreach and onward, the variable rowId just... disappears. Everything is fine for the first Foreach (the makeDatabaseCanvas method works perfectly), but for the 2nd one, and onward, the console return the rowId is null. Here is the error returned.
At this point, I have tried many solutions. I tried async/await but Foreach expects a synchronous function. I tried replacing it with For loop and... it returned nothing. I tried to put the name of the document inside an array and use async/await on it, but it also failed.
Thank you in advance.
EDIT: The error comes from the code to get the canvas id from the rowId (because I link them together for easier coding). Since it cannot access rowId, it cannot access the canvas id as well. I have editted the codes a bit to make them easier to be shown on Stackoverflow. So the whole codes are like that.
And as you can see in the picture, the first one is drawn perfectly. However, the second one cannot be drawn. The id does not increase, and the id of the 2nd canvas is 'db-canvas-0' where it should be 1.
CodePudding user response:
Change this line of code:
dbRef.doc(doc.data().name).collection("canvas").get()
to
dbRef.doc(doc.id).collection("canvas").get()
You should reference the document itself rather than referencing on the document's data object.
You could also check the code that I wrote which also gets data from the collection, documents and its subcollection.
dbRef = db.collection("collection");
let rowId = 0;
dbRef.get().then((querySnapshot) => {
querySnapshot.forEach((document) => {
document.ref.collection("sub_collection").get().then((querySnapshot) => {
//Prepend Row HTML Data.
console.log(['main_collection_data: ', rowId, document.data()]);
rowId ;
querySnapshot.forEach((document) => {
// Get the circles from the database in each row
console.log(['sub_collection_data:', document.data()]);
});
})
})
});


