How to assign snap.val() to the global variable? - angularjs

I want to assign snap.val() to this.Productslike this.Products= snap.val(); but this.Products is undefined in that scope.
Products: FirebaseListObservable<any>;
constructor(){
}
ionViewDidLoad(){
this.angularFire.database.list('/Products').$ref.orderByChild('uid')
.equalTo('NW1Kq4WB7ReUz2BNknYWML9nF133').on('child_added', function(snap){
console.log(snap.val().name);
//this.Products= snap.val();
});
}
I tried the following code when snap is returned ,but I receive this message -- No index defined for uid:
snap.forEach(SnapShot=>{
console.log(SnapShot.val().name)
My Firebase database:
"Products" : {
"-Kbx0i-TFeTyRbNZAZ_8" : {
"category" : "1",
"detail" : "xxxxx details",
"name" : "xxxxx",
"uid" : "NW1Kq4WB7ReUz2BNknYWML9nF133"
}
Please help. Thanks.

The directly answer the question you asked, you can use an ES6 arrow function:
let query = this.angularFire.database.list('/Products').$ref.orderByChild('uid')
.equalTo('NW1Kq4WB7ReUz2BNknYWML9nF133');
query.on('child_added', (snap) => this.Products= snap.val());
Or for ES5 compatibility, declare this as a variable:
let self = this;
let query = this.angularFire.database.list('/Products').$ref.orderByChild('uid')
.equalTo('NW1Kq4WB7ReUz2BNknYWML9nF133');
query.on('child_added', function(snap) {
self.Products= snap.val();
});
But in reality, this is an XY problem and you don't want what you think you want here.
What you've done is reimplement the list yourself, and defeat the entire purpose of AngularFire2, which handles all this synchronization on your behalf.
Additionally, you've mis-used child_added by assigning each record you get back (you get an array of results, not exactly one) to this.products, when you probably wanted to set this.products = [] and then use this.products.push(snap.val()) for each child_added invocation.
So what you really want here, is to use AngularFire's built-in queries and avoid this entire mess :)
this.products = af.database.list('/Products', {
query: {
orderByChild: 'uid',
equalTo: 'NW1Kq4WB7ReUz2BNknYWML9nF133'
}
});

I did it in this way:
import firebase from "firebase";
const firebaseConfig = {
your firebaseConfig...
};
let app = firebase.initializeApp(firebaseConfig);
let database = firebase.database();
export async function readFromFirebase(userId, key) {
const ref = database.ref("users/" + userId + "/" + key);
const snapshot = await ref.once("value");
return snapshot.val();
}
async function main() {
console.log(await readFromFirebase(109512127, "userName"));
}
main();

Related

NextJS Global Variable with Assignment

I'm new to NextJS, and trying to figure out, how to create a global variable that I could assign a different value anytime. Could someone give a simple example? (I know global might not be the best approach, but still I would like to know how to set up a global variable).
Let's say:
_app.js
NAME = "Ana" // GLOBAL VARIABLE
page_A.js
console.log(NAME) // "Ana"
NAME = "Ben"
page_B.js
console.log(NAME) // "Ben"
try using Environment Variables
/next.config.js
module.exports = {
env: {
customKey: 'my-value',
},
}
/pages/page_A.js
function Page() {
return <h1>The value of customKey is: {process.env.customKey}</h1>
}
export default Page
but you can not change its contents, except by changing it directly in next.config.js
Nextjs no special ways to provide global variables you want. You can achieve by:
Stateful management tool, like redux-react
Using Context
It's not like it's impossible,
I created a file called _customGlobals.jsx and put this as content
String.prototype.title = function () {
const sliced = this.slice(1);
return (
this.charAt(0).toUpperCase() +
(sliced.toUpperCase() === sliced ? sliced.toLowerCase() : sliced)
);
};
and imported it in _app.jsx like this:
import "./_customGlobals";
So now I can call this function on any string anywhere in my project like this:
"this is a title".title()
Database designed for this purpose. But for one var it's not wise to install whole db!
So, you can do it in a JSON file.
Add a var to a JSON file and use a function to update it.
this is a simple function for this usage:
const fs = require('fs');
function updateJSONFile(filePath, updates) {
fs.readFile(filePath, 'utf8', function (err, data) {
if (err) {
console.error(err);
return;
}
let json = JSON.parse(data);
for (let key in updates) {
json[key] = updates[key];
}
fs.writeFile(filePath, JSON.stringify(json, null, 2), 'utf8', function (err) {
if (err) {
console.error(err);
}
});
});
}
So, use it like this:
updateJSONFile('file.json', { name: 'John Doe', age: 30 });
You can create another function to read it dynamicly:
function readJSONFile(filePath) {
fs.readFile(filePath, 'utf8', function (err, data) {
if (err) {
return callback(err);
}
let json;
try {
json = JSON.parse(data);
} catch (error) {
return callback(error);
}
return callback(null, json);
});
}
and you can use it like this:
const readedFile = readJSONFile('file.json')
I deleted the callback function to have a simple code but you can add callback function to log error messages.

Can't figure out why array length is undefined

I keep receiving the following message in my console, "Uncaught (in promise) TypeError: Cannot read property 'length' of undefined"
quotesData.quotes should be the key for an array, however, so I'm unsure as to why its length property is undefined.
quotesData should be a JSON object that looks like: { "quotes": [Object1, Object2, ...etc.]}
Is there something wrong with how I'm using axios? I'm still very new to programming in general and quite new to react.js
getQuote() {
let _this = this;
_this.serverRequest =
axios
.get("https://raw.githubusercontent.com/dwgillette/quotes/master/library")
.then(function(quotesData) {
console.log(quotesData);
let newQuote = quotesData.quotes[Math.floor(Math.random() * quotesData.quotes.length)];
_this.setState({
quote: newQuote.quote,
author: newQuote.author
});
})
}
So the data you want is actually going to be on a .data attribute of the response. So if you fix your code up like this you will be good to go :)
getQuote() {
let _this = this;
_this.serverRequest =
axios
.get("https://raw.githubusercontent.com/dwgillette/quotes/master/library")
.then(function(q) {
quotesData = q.data;
console.log(quotesData);
let newQuote = quotesData.quotes[Math.floor(Math.random() * quotesData.quotes.length)];
_this.setState({
quote: newQuote.quote,
author: newQuote.author
});
})
}
Because the promise resolves to response object. Try doing:
getQuote() {
let _this = this;
_this.serverRequest =
axios
.get("https://raw.githubusercontent.com/dwgillette/quotes/master/library")
.then(function(response) {
let newQuote = response.data.quotes[Math.floor(Math.random() * response.data.quotes.length)];
_this.setState({
quote: newQuote.quote,
author: newQuote.author
});
})
}
Here is a screenshot of the response object you are getting back.
I refactored your code to work. you need to use res.data.
getQuote = () => {axios.get("https://raw.githubusercontent.com/dwgillette/quotes/master/library")
.then(res => {
let newQuote =
res.data.quotes[Math.floor(Math.random() * res.data.quotes.length)];
this.setState({
quote: newQuote.quote,
author: newQuote.author
});
});
};

Why this setState is not a function in ComponenDidMount?

I am trying to fetch ordered data from Firebase and set it to state highscoreArray but it gives error "undefined is not a function (evaluating 'this.setState({ highscoreArray:sortedHighscores })')
componentDidMount() {
const reference = database.ref("highscores");
// Pushing sorted data to highscoreArray.
reference.orderByChild("highscore").limitToLast(3).on("value", function (snapshot) {
sortedHighscores = [];
snapshot.forEach(function (child) {
sortedHighscores.push({
"username": child.val().username,
"score": child.val().highscore
});
});
sortedHighscores = sortedHighscores.reverse();
console.log("sortedh", sortedHighscores); // fetch success
this.setState({highscoreArray: sortedHighscores}); // gives error
});
}
One of the major advantages of arrow functions is that it does not have it's own this value. It's this is lexically bound to the enclosing scope.
class Logger {
dumpData(data) {
var _this = this;
// this dumps data to a file and get the name of the file via a callback
dump(data, function (outputFile) {
_this.latestLog = outputFile;
});
}
}
// using arrow functions
class Logger {
dumpData(data) {
dump(data, outputFile => this.latestLog = outputFile);
}
}
1.this not accessible within loop so use variable let that = this the use that wherever you need this in this function.
componentDidMount() {
const reference = database.ref("highscores");
let that = this // here your variable declaration
// Pushing sorted data to highscoreArray.
reference.orderByChild("highscore").limitToLast(3).on("value", function (snapshot) {
sortedHighscores = [];
snapshot.forEach(function (child) {
sortedHighscores.push({
"username": child.val().username,
"score": child.val().highscore
});
});
sortedHighscores = sortedHighscores.reverse();
console.log("sortedh", sortedHighscores); // fetch success
that.setState({highscoreArray: sortedHighscores}); // gives error
});
}
Hope this will help you :) happy coding!
Inside the function callback the this has a different context. Either use an arrow function, or store a reference outside:
Arrow:
reference.orderByChild("highscore").limitToLast(3).on("value", (snapshot) => { ... });

Extending $firebaseArray with an extended $firebaseObject

Trying to cut down code repetition, I've set up a $firebaseArray extension as follows:
var listUsersFactory = $firebaseArray.$extend({
$$added: function (snap) {
return new Customer(snap);
},
$$updated: function (snap) {
var c = this.$getRecord(snap.key);
var updated = c.updated(snap);
return updated;
},
});
and the Customer code:
function Customer(snap) {
this.$id = snap.key;
this.updated(snap);
}
Customer.prototype = {
updated: function(snap) {
var oldData = angular.extend({}, this.data);
this.data = snap.val();
// checks and such
}
}
This works wonders when loading, showing and saving a list of customers, and I'm satisfied with it.
Now, the problem lies in retrieving a single customer and its detail page, because the Customer object isn't an extension of $fireObject and is therefore lacking a $save method
Single customer loading:
customersRef.once("value", function(snapshot) {
if(snapshot.child(uuid).exists())
{
customersFactory.customerDetails = new Customer(snapshot.child(uuid));
return deferred.resolve();
}
}
but when I call customersFactory.customerDetails.$save() I get an error
How can I extend my class so that it works for both array and single object uses?
I couldn't find a way to do this, so I ended up using the $firebaseArray and getting single records off that to pass as details, in case anyone's wondering

update in firebase is not working(with React) [duplicate]

I am quite new to firebase and i am trying to retrieve particular data. and getting this error,
Please help me with this.
My code looks like this
var t1= this.password.value;
var user_id = this.state.comments[2];
firebase.database().ref(user_id).orderByChild("Password").equalTo(t1).on("child_added", (snapshot) => {
var datas1 = []
snapshot.forEach((data1) =>
{
datas1.push( {
username: data1.val().Username,
password: data1.val().Password,
});
});
this.setState ({
datas1: datas1,
});
});
console.log(this.state.datas1);
even the array datas1 is coming empty.

Resources