i have a data structure as below
I created an array called new array with the IDs such as [19777873, 53399293]
var dbRef = firebase.database().ref().child('Agents').child(newarray[i]);
dbRef.on('value', snapshot => {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
database = firebase.database();
console.log("Testing if the array values are here \n" + newarray);
// var dbRef = firebase.database().ref().child('Agents').child(newarray[i]);
dbRef.on('value', newAgents, errData);
}
})
}
New Agent function
function newAgents(data) {
var container = document.getElementById("team");
container.innerHTML = '';
data.forEach(function(AgentSnap) { // loop over all jobs
var key = AgentSnap.AgentID;
console.log(AgentSnap.key);
var Agents = AgentSnap.val();
var AgentCard = `
<div class= "profilepics" id="${key}">
<figure ><img src=${Agents.profilepicurl}><figcaption>${Agents.Fname}</figcaption></figure>
</div>
`;
container.innerHTML += AgentCard;
})
}
the problem I'm having now is that images(from {Agents.profilepicurl}) are being displayed and name (from {Agents.Fname}) are not being displayed. instead of name it shows "undefined" and no error is show in console. What am I doing wrong and how can I fix this?
There are some strange things happening in the first few lines of your code. You are setting the "on" listener twice (ignoring the resulting snapshot for the first listener), and you're awaiting authentication and setting a database object without using it. I am not absolutely certain about what you're trying to achieve, but would this work? It's a simplified version of what I think you're trying to do with the current code:
console.log("Testing if the array values are here \n" + newarray);
firebase.auth().onAuthStateChanged((user) => {
if (user) {
document.getElementById("team").innerHTML = '';
database = firebase.database();
for (agentId of newarray) {
var dbRef = database.ref().child('Agents').child(newarray[i]);
dbRef.on('value', newAgents);
}
}
})
function newAgents(AgentSnap) {
var container = document.getElementById("team");
var key = AgentSnap.AgentID;
console.log(AgentSnap.key);
var Agent = AgentSnap.val();
var AgentCard = `
<div class= "profilepics" id="${key}">
<figure ><img src=${Agent.profilepicurl}><figcaption>${Agent.Fname}</figcaption></figure>
</div>
`;
container.innerHTML += AgentCard;
}
Related
i know that the problem is that let todoList is an empty array, but i dont know how to solve it.
the id tags in my created html is so e can create a delete button later
heres my code:
const textArea = document.querySelector("textarea");
const button = document.querySelector("button");
const listContainer = document.querySelector(".list-container");
let id = 0;
let todoList = [];
button.onclick = function () {
const listItem = {
title: textArea.value,
};
todoList.push(listItem);
addToStorage(todoList);
const dataFromStorage = getFromStorage();
createHtml(dataFromStorage);
};
function addToStorage(items) {
const stringify = JSON.stringify(items);
localStorage.setItem("list", stringify);
}
function getFromStorage() {
const data = localStorage.getItem("list");
const unstrigified = JSON.parse(data);
return unstrigified;
}
const createHtml = (data) => {
id++;
listContainer.innerHTML = "";
data.forEach((item) => {
listContainer.innerHTML += `<div class="list-item" data-id=${id}><p>${item.title} </p><button class="remove" data-id=${id}>Delete</button></div>`;
});
};
The problem here is you just forgot to load the data from localStorage when the page loaded like this
window.onLoad = () => {
const dataFromStorage = getFromStorage();
if(dataFromStorage){
createHtml(dataFromStorage);
} else {
createHtml([]);
}
}
The problem in the code is as follows
Initially the todolist will be an empty array. so when you do the below
todoList.push(listItem);
// adding to local storage which will override the existing todos when page is refreshed
addToStorage(todoList);
// So when the below line is executed only the latest todo will be returned
const dataFromStorage = getFromStorage();
createHtml(dataFromStorage);
Fix:
Initialise the todos from localstorage instead of an empty array
let todoList = [];
// change it as below
let todoList = getFromStorage();
Now Modify the getFromStorage() as below
// If the data is present in the localStorage then return it, else return empty array
function getFromStorage() {
const data = localStorage.getItem("list");
if (!data) return [];
const unstrigified = JSON.parse(data);
return unstrigified;
}
Now when the page is loaded, we need to display the todos. Add the below lines of code
window.onload = function () {
createHtml(todoList);
};
That's it. This will fix the issue.
Few minor improvements can be made as well.
todoList.push(listItem);
addToStorage(todoList);
const dataFromStorage = getFromStorage(); // this line is not necessary, remove it
createHtml(dataFromStorage); // change this to createHtml(todoList)
Codepen
Thanks.
I have queried my firebase database to count the number of people that have subscribed to topics. I have received the results in the console.log() and I would like to display the results on a webpage in the div customerNumber. The code below displays the same number next to each topic even though the correct number is diplayed under each topic in the console.log(). How do I correct this?
This is my HTML code:
<div class="rh_topic" title="Title" ></div>
<div class="customerNumber"></div>
This is my code in my javascript file.
function countSubscribers () {
const topics = document.querySelectorAll(".rh_topic");
topics.forEach(topic => {
let number = topic.title;
const ref = firebase.database().ref('topics/' + number);
ref.once("value")
.then(function(snapshot) {
console.log(topic.title);
console.log(snapshot.numChildren());
let customers = snapshot.numChildren();
const elements = document.getElementsByClassName('customerNumber');
Array.prototype.forEach.call(elements, function(element) {
element.textContent = customers;
});
});
});
}
countSubscribers();
to simplify, you can just use
elements.map((elements, indexEl) => {
elements.innerText = customers
return true;
})
So I have a loop which is displaying the user data as expected (this works fine):
database.once("value", function(snapshot){
snapshot.forEach(snap => {
var r = document.getElementById('userTable').insertRow()
var age = r.insertCell(0).innerHTML = snap.val().key;
var aboutme = r.insertCell(1).innerHTML = snap.val().photourl;
})
The user image is stored in firebase storage like so (clicking into the folder which contains the image):
My user table looks like this:
With all the associated fields linked to that user under that and the photo_url holds the image path like:
user_photos/07KSLIkK2/D41FB90B444D-9979-22F86D69883F.jpg
Ive tried looking online but most of the answers or solutions are for android. Im pretty new to firebase.
So the question is how can i display the associated image from firebase for the user in the html table?
Thanks
Also, using:
snap.val().key; does not show that random generated number by firebase. just shows as undefined.
UPDATE
was having some difficulties so just for testing purposes i split the code up like so:
database.once("value", function(snapshot){
snapshot.forEach(snap => {
var storageRef = firebase.storage().ref();
var temp_photo = storageRef.child('ref_name/mas.jpg')
console.log(temp_photo);
temp_photo.getDownloadURL().then(downloadURL => {
var Photo_url = document.getElementById('images').innerHTML = downloadURL;
})
})
})
In my HTML i have the following:
<div id="images" class=""></div>
what this should do is display that one images for each set of data it pulls. Below are console logs (which are repeated for each set of data its pulling)
authWrapper: Qe
app_: T {firebase_: Object, isDeleted_: false, services_: Object, tokenListeners_: Array, analyticsEventRequests_: [], …}
bucket_: "dbucketname"
deleted_: false
maxOperationRetryTime_: 120000
maxUploadRetryTime_: 600000
pool_: G {createXhrIo: function}
requestMaker_: function(e,t,r)
requestMap_: Ze {map: Map, id: -9007454433453423, addRequest: function, clear: function}
service_: nt {bucket_: J, authWrapper_: Qe, app_: T, internals_: it, ref: function, …}
storageRefMaker_: function(e,t)
Qe Prototype
location: J
bucket: "dbucketname"
path_: "ref_name/mas.jpg"
In the div it displays 1 row of the following:
https://firebasestorage.googleapis.com/v0/b/app.appspot.com/o/ref_name%2Fmas.jpg?alt=media&token=11111111-1111-1111-1111-11111111111
UPDATE 2
So it got it to work like so
database.once("value", function(snapshot){
snapshot.forEach(snap => {
var storageRef = firebase.storage().ref();
var temp_photo = storageRef.child('ref_name/mas.jpg')
console.log(temp_photo);
temp_photo.getDownloadURL().then(downloadURL => {
var x = document.createElement("IMG");
x.setAttribute("src", downloadURL);
document.body.appendChild(x);
})
})
})
its looping around each user and displaying the picture as expected.
But when i try to move this logic to put this image into a table, i get the following error:
IndexSizeError: The index is not in the allowed range.
this is what my table insert code looks like:
var occupant = r.insertCell(16).innerHTML = snap.val().occupation;
var storageRef = firebase.storage().ref();
var temp_photo = storageRef.child('ref_name/mas.jpg')
temp_photo.getDownloadURL().then(downloadURL => {
var x = document.createElement("IMG");
x.setAttribute("src", downloadURL);
r.insertCell(17).appendChild(x)
})
var you_smoke = r.insertCell(18).innerHTML = snap.val().smoke;
UPDATE 3 - SOLUTION
This is what worked for me:
var storageRef = firebase.storage().ref();
var temp_photo = storageRef.child('ref_name/mas.jpg')
var y = r.insertCell(17).innerHTML = snap.val().photo_url;
temp_photo.getDownloadURL().then(downloadURL => {
var y = r.insertCell(17).innerHTML = '<img src="'+downloadURL+'" width="20" height="20" />';
})
To get the key of the DataSnapshot, you need to do snap.key, see the doc for the key property.
To get the URL of an image stored in Cloud Storage for Firebase, with the JavaScript SDK, you should use the getDownloadURL() method of a Reference.
Note that this method is asynchrnonous and therefore you need to do as follows:
ref.getDownloadURL().then(function(downloadURL) {
//console.log('File available at', downloadURL);
});
Which means, in your case, that you should do something along the following lines (If I have correctly understood your data structure):
database.once("value", function(snapshot){
snapshot.forEach(snap => {
var r = document.getElementById('userTable').insertRow()
var age = r.insertCell(0).innerHTML = snap.key;
//var aboutme = r.insertCell(1).innerHTML = snap.val().photourl;
var photRef = storageRef.child('user_photos/' + snap.key + '/' + snap.val().photourl);
photRef.getDownloadURL().then(downloadURL => {
var aboutme = r.insertCell(1).innerHTML = downloadURL;
});
})
Thanks to #RenaudTarnec's help this is the solution that worked:
var storageRef = firebase.storage().ref();
var temp_photo = storageRef.child('ref_name/mas.jpg')
var y = r.insertCell(17).innerHTML = snap.val().photo_url;
temp_photo.getDownloadURL().then(downloadURL => {
var y = r.insertCell(17).innerHTML = '<img src="'+downloadURL+'" width="20" height="20" />';
})
this question is probably really easy but I kind of got stuck with Firestore. It's my first project with firestore + js and I'm trying to receive and display data from my database. I have a feeling that I am doing something really stupid because it seems like I am looping through my data and overriding it that's why I can see only one article element even though there should be 2 fetched from the database.
document.addEventListener('DOMContentLoaded', event => {
const app = firebase.app();
const db = firebase.firestore();
const myProducts = db.collection('products');
myProducts.onSnapshot(products => {
const productsContainer = document.querySelector('#products__container');
products.forEach(doc => {
data = doc.data();
console.log(data);
let productMarkup = `<article id="${doc.id}">
<h4>${data.name}</h4>
<p>${data.price}</p>
</article>`;
productsContainer.innerHTML = productMarkup;
console.log(productMarkup);
});
});
});
After Alex suggestion, I decided to take the different approach to create DOM elements
const db = firebase.firestore();
const myProducts = db.collection('products');
const productsContainer = document.querySelector('#products__container');
function renderProduct(doc) {
const docFrag = document.createDocumentFragment();
let article = document.createElement('article');
let productName = document.createElement('h4');
let productPrice = document.createElement('p');
article.setAttribute('id', doc.id);
productName.textContent = doc.data().name;
productPrice.textContent = doc.data().price;
docFrag.appendChild(productName);
docFrag.appendChild(productPrice);
article.appendChild(docFrag);
productsContainer.appendChild(article);
}
myProducts.onSnapshot(products => {
products.forEach(doc => {
data = doc.data();
console.log(data);
renderProduct(doc);
});
});
});```
I have two tasks. They have to get values from Firebase Firestore. Here is my JavaScript:
if (doc.exists) {
console.log("Document data:", doc.data());
const data = doc.data();
const members = data.members;
var permission_table = document.getElementById("noten_tabelle_permission");
var permission_table_container = document.getElementById("main_padding");
members.forEach(el => {
console.log(el)
table_number++;
const html = fillTemplate("grade_table" + table_number, doc.id);
// Join the array of html and add it as the `innerHTML` of `main`
document.getElementById("main_padding").insertAdjacentHTML('beforeend', html);
db.collection("users").doc(el).collection("grades").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
const data = doc.data();
addToTable("grade_table" + table_number, doc.id, data.mdl, data.klu);
});
});
})
} else {
console.log("No such document!");
}
So first as you can see I am getting the "members" from Firestore. Then I create for each one a table with a different id. By the way. Here is the "fillTemplate" Function:
function fillTemplate({ table_name, id }) {
return `
<div class="noten_tabelle_permission" id="noten_tabelle_permission">
<h1 id="member_name">${id}</h1>
<table id="${table_name}" style="width:100%">
<tr>
<th>Fach</th>
<th>mündlich</th>
<th>Klausur</th>
</tr>
<!-- Make content with js code -->
</table>
</div>
`;
}
So after joining table to main view, I am searching for each user ( === or for each table) the values. I add them to the table by calling the "addToTable" function, you can see here:
function addToTable(table_name, subject, mdl, klu) {
var subject_name = getSubjectByNumber(subject);
var short_subject = getSubjectShortByNumber(subject);
var y = document.createElement([short_subject]);
y.setAttribute("id", [short_subject]);
document.getElementById([table_name]).appendChild(y);
var y = document.createElement("TR");
y.setAttribute("id", [short_subject]);
var cE = document.createElement("TD");
var tE = document.createTextNode([subject_name]);
cE.appendChild(tE);
y.appendChild(cE);
var a = document.createElement("TD");
var b = document.createTextNode([mdl]);
a.appendChild(b);
y.appendChild(a);
var c = document.createElement("TD");
var d = document.createTextNode([klu]);
c.appendChild(d);
y.appendChild(c);
document.getElementById(table_name).appendChild(y);
}
But now I am getting this Error: Uncaught (in promise) TypeError: Cannot read property 'appendChild' of null in this line: document.getElementById([table_name]).appendChild(y);. I think it is because Firebase is asynchronous. But how to fix this? How to code it that it strictly get the values for the member and start first than with the next member?
The id of the tables is the string "grade_table" and the number of the var table_number. The id is needed even for the second firebase task. But since the first Firebase task loads asynchronous the var table_number is updated instantly with this line: table_number++;. So the next task of firebase has the wrong table id.
~marcelo