Firebase retrieve returns undefined/object Object - javascript

I'm currently working on retrieving a child from Firebase with this code:
function fetchUserdetails() {
firebase.database().ref().child('login/').orderByChild('username').equalTo('ivanaldwin').on("value", function(snapshot) {
document.getElementById('fullname').innerHTML = snapshot.val().username;
console.log(snapshot.val()); //debug in console
snapshot.forEach(function(data) {
console.log(data.key);
alert('yep im working dood');
});
});
}
window.onload = fetchUserdetails();
But the code, if i use snapshot.val().username; will render undefined in the output. but if i use snapshot.val() only, the output will be [Object object]. Here's my firebase layout:

To retrieve the username try the following:
snapshot.forEach(function(data) {
let userName = data.val().username;
console.log(data.key);
alert('yep Im working dude');
});
Your snapshot is at node login, therefore after you loop using forEach you then can access the child attributes.

You need to use array index
document.getElementById('fullname').innerHTML = snapshot.val()[0].username;
But I think you would need the element 0 for that one, which you don't have.
Maybe try
document.getElementById('fullname').innerHTML = snapshot.val().child('1').username

Related

Dynamically get data from firebase realtime database during runtime in javascript

I have the following problem: I want to get data from a specific node from firebase during runtime. It should display "stats" of a player that was selected before. Now I could use on() to get all the data in the beginning, but I want to save data transfers by only downloading the data of on player if I need to, so I tried to use once like this:
var firebaseRef = firebase.database().ref();
function getScoresOfPlayer(player) {
console.log(player);
var selectedPlayerScores = [];
firebaseRef.once('value').then(function(snap) {
snap.child('scores').child('thierschi').forEach(function(child) {
selectedPlayerScores.push([child.key, child.val()]);
});
});
return selectedPlayerScores;
}
The problem is that it retruns the array before the data was loaded into it. Also I checked the docs and didn't find a better solution.
Thanks in advance!
This is because the getScoresOfPlayer function returns selectedPlayerScores before the promise returned by the once() method resolves.
You should include the return within the then(), as follows:
var firebaseRef = firebase.database().ref();
function getScoresOfPlayer(player) {
console.log(player);
var selectedPlayerScores = [];
return firebaseRef.once('value') //return here as well
.then(function(snap) {
snap.child('scores').child(player).forEach(function(child) { //I guess it should be child(player) and not child('thierschi') here
selectedPlayerScores.push([child.key, child.val()]);
});
return selectedPlayerScores;
});
}
which means that you have to call your function as follows, since it is going to be asynchronous and to return a promise:
getScoresOfPlayer('xyz')
.then(function(selectedPlayerScores) {
....
})

Firebase - Getting first value of last child Javascript

Attempting to read the Temp value of the last child in the following Firebase structure, however unable to read the child value.
Firebase Database Structure below:
Attempted code;
//GET last child and return val for temperature;
var lastChild_Light = firebase
.database()
.ref()
.child("av")
.child("data")
.child("01230C3DB6717F1DFE")
.limitToLast(1)
.child("Temp");
lastChild_Light.on("value", function(lastdatasnap) {
document.getElementById("lastTemp").innerText = lastdatasnap.val();
});
The idea is for the user to see the latest temp value, once they land on webpage.
If you are looking Javascript solution the following would work
firebase.database().ref('io/av/data/01230C3DB6717F1DFE/').limitToLast(1).on('child_added', function(snapshot) {
console.log(snapshot.val()); // gives key and value pair - {Temp: "35.43"}
snapshot.forEach((child) => {
console.log(child.val()); // gives value of key
});
});
This could be of more help.

Google Firebase: snap.val().username returns undefined

I get the item in the realtime database where the email child equals the email in the localStorage and that works just fine.
however when i try to log the username, it returns undefined instead of the actual username
let useremail = localStorage.getItem("useremail")
firebase.database().ref("/users").orderByChild('email').equalTo(useremail).on("value", function(snap){
let data = snap.val();
console.log(data.username)
})
Anyone knows how to fix this?
database looks like this
If i log data this shows:
and If i log useremail the correct string does show
Try this:
let useremail = localStorage.getItem("useremail")
firebase.database().ref("/users").orderByChild('email').equalTo(useremail).on("value", function(snap){
snap.forEach(function(childSnapshot)){
let data = childSnapshot.val();
console.log(data.username)
});
});
Since reference is at node users then you need to loop to be able to access the attributes.

Getting Array out of JavaScript Object

I try to get messages from a Server via Websocket and this works so far.
I get back an Javascript Object and want to filter out the data I need to put it into the state of my react app.
this is the code im using at the moment:
connection.onmessage = function (newMessage) {
if(newMessage.data == '{"msg":"ping"}' ){
connection.send('{"msg": "pong"}')
}
newMessage = JSON.parse(newMessage.data)
console.log(newMessage.fields)
}
and this is the object I get back:
Javascript Object
I need the Array at args/0
how do i get it?
Thank You
It's probably not a good idea to rewrite newMessage in your connection.onmessage function, and may be add more logs when you get a new message. Can you try this version ?
connection.onmessage = function (newMessage) {
console.log("Received new message :", newMessage.data);
if(newMessage.data == '{"msg":"ping"}' ){
connection.send('{"msg": "pong"}')
}
var parsedMessage = JSON.parse(newMessage.data);
if (parsedMessage.msg === "changed") {
console.log("Received changed message :", parsedMessage.fields.args);
}
}
Hope this helps!
you can access the 'args' data in the json object like 'newMessage.args'
var newMessage = {eventName: 'aname', args: ['data1','data2'] }
document.getElementById('output').innerHTML = newMessage.args
<div id='output'></div>

Firebase update() not a function with a query

I'm trying to update a property in a record in Firebase Database, with AngularJS. I can set up a query to find my record:
firebase.database().ref('en/').orderByChild('word').equalTo('the').once('value')
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
console.log(childSnapshot.val())
});
})
I can update my property, if I hardcode in the record's key:
firebase.database().ref('en/-KloeQHDC-mugPjJMAG4').update({ wordFrequency: 111 })
But if I set up a query to find the record and then update it, I get an error message update is not a function:
firebase.database().ref('en/').orderByChild('word').equalTo('the').update({ wordFrequency: 9001 })
Another answer suggests calling update() from inside a forEach loop:
firebase.database().ref('en/').orderByChild('word').equalTo('the').once('value')
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
console.log(childSnapshot.val()); // this works
childSnapshot.ref().update({ wordFrequency: 9001 });
});
});
That returns an error message TypeError: childSnapshot.ref is not a function. I don't see how childSnapshot is a Firebase ref.
Another answer says
When you call update() on a location, Firebase loops over the data
that you pass in (in your case asJson) and for each key performs a
ref.child(key).set(value).
If update() loops over the data, why should I call update() from inside a forEach loop? The documentation doesn't show calling update() from inside a forEach loop.
The Firebase Database SDK provides a Reference.update() method to update data in a single location in a database. Key here is that a Reference is a single location in the database, so it is clear what to update.
My pseudo-code explanation about how multi-path updates work applies to how the database server implements it: given a single location/DatabaseReference it updates each path in the update() call based on that.
A Query can match multiple locations in the database, so it doesn't have an update() method (or set() or remove() for that matter).
To update each location matched by a query, you execute the query and then call update() on each result - either by a child_added listener, or with a value listener and a loop like in your last snippet.
After I posted this question I walked the dog, ate dinner, and then the solution came to me. My new rule is, "The key to Firebase queries is to keep track of the key."
This template is for users to update records in the database. They enter a search term in a form field and click the "Search" button. The $scope.search handler queries the Firebase database and then populates the form fields with the record's properties:
$scope.search = function() {
myFirebase_ref.orderByChild('word').equalTo($scope.word).once('value')
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
$scope.wordKey = childSnapshot.key;
$scope.audioArray = childSnapshot.val().audio;
$scope.ipaArray = childSnapshot.val().ipa;
$scope.language = childSnapshot.val().language;
$scope.longLanguage = childSnapshot.val().longLanguage;
$scope.phonemeArray = childSnapshot.val().phonemes;
$scope.translationArray = childSnapshot.val().translations;
$scope.word = childSnapshot.val().word;
$scope.wordFrequency = childSnapshot.val().wordFrequency;
$scope.$apply();
});
})
.catch(function(error) {
console.error("Authentication failed:", error.message);
});
};
Note at the top of the property assignments I have $scope.wordKey = childSnapshot.key;. I'm keeping track of the record's key.
The user then updates a field. Each field has a button next to it for "Update". Each button goes to a handler. For example, to update the wordFrequency field I have this handler:
$scope.updateFrequencyRank = function() {
firebase.database().ref('en/' + $scope.wordKey).update({ wordFrequency: $scope.wordFrequency })
};
One line of code and it works! Even better, I made an onComplete function to tell me if the update succeeded:
$scope.updateFrequencyRank = function() {
var onComplete = function(error) {
if (error) {
console.log('Update failed');
} else {
console.log('Update succeeded');
}
};
firebase.database().ref('en/' + $scope.wordKey).update({ wordFrequency: $scope.wordFrequency }, onComplete);
};

Categories