I'm so stuck on this I might not even be able to formulate a sensible question, but here goes...
I have a gigantic (and occasionally changing) form. I've found a reasonable way to get all the data from the form, turn it into an object, and save it to Firebase all at once. It looks like this, and is working fine (I think):
const incidentReport = document.getElementById('incident-report-form');
let irv = {};
// This works. All form data is saved to an object (as required by firebase), with the question as the name and the answer as the value.
incidentReport.addEventListener('submit', (e) => {
e.preventDefault();
[...incidentReport.elements].forEach((item) => {
let name = item.name;
let value = item.value;
irv = { ...irv, [name]: value };
});
// After all data is collected in one object, I send it to the database all at once.
db.collection('incident reports').add(irv);
});
Okay, so far so good... Now I want to get it back out of the database (I know how to do this) and repopulate the same form (no idea). I'm 100% stumped and I don't even know what to try.
Please forgive me if this is super easy and my brain is just shutting off... it's been a rough day.
Thanks in advance.
EDIT - This seems to work? I'm still very open to criticism and/or improvements.
// Get data from incident reports
//#TODO -> Need to create a list of incident reports, and then load the one //the user clicks on.
//Right now there is only one incident report in the database for testing.
db.collection('incident reports')
.get()
.then((snap) => {
snap.docs.forEach((element) => {
data = element.data(); //Previously declared but not included in this snippet, sorry.
});
for (let [key, value] of Object.entries(data)) {
let x = document.getElementsByName(key)[0];
if (x !== undefined) {
x.value = value;
}
}
});
If I understood it correctly, once you returned the data from your Firestore collection, you want to print them back in your HTML form. Considering that, it should not be very hard for you to achieve that.
Once you load the documents into an array, you should be able to assign the values to variables, that will be printed in the form. It should be something like this:
//Getting the collection and a specific document
var report = db.collection('incident reports').doc('<report>');
var getDoc = report.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
// Loading the values of the document into variables
var name = getDoc.data().name;
var value = getDoc.data().value;
...
// Other values loaded to other variables that you create
}
})
.catch(err => {
console.log('Error getting document', err);
});
Once you have loaded the values into variables, you just need to create a tag <script> that will be adding the values via Javascript into your HTML. Something that can look like this:
<script src="http://code.jquery.com/jquery-3.4.1.min.js"></script>
document.getElementById('<form item name>').innerHTML = name;
</script>
While this code is not tested, I believe it should be a good starting point for you, on what you need to do, to achieve your goal. It's only for one document, but since you are on tests right now and have only one document, you should be fine.
Besides that, you can find a good and full example on retrieving values from Firestore and priting in a page, in this other post here: How can I display all data from Firestore documents into html elements
Let me know if the information helped you!
Related
I have an issue with saving items into an array in JavaScript/Next.js.
At the beginning I have an empty array. Then a session is started, and I check if the session is empty or not. If it is empty, I write a response of a get-request into a variable. At the same time I also write the response of the get request into localstorage.
Basically I now want to write the value of localstorage into the array with the push-method.
In the next step my program should realize, that the session is not empty anymore and now the new value of the get-request should be stored into localstorage and at the same time it should be added as a new element of the variable. The old elements of the array should not be overwritten. I have now tried a couple of things, but I could not get it to work.
Does anybody have a hint for me, how to realize this problem? I would be very thankful, if anybody could help me on this one 😊
api.get('products?include=' + mainId, addOrViewCartConfig).then((response) => {
if (isEmpty(storedSession)) {
storeSession(response.data[0].id);
localStorage.setItem('ID', response.data[0].id);
var localCart = [];
};
if (!localCart.indexOf(parseInt(localStorage.getItem('ID')))) {
localCart.push(parseInt(localStorage.getItem('ID')));
} else {
alert('The item you are trying to add is already in your cart!');
return false;
}
viewCart();
}).catch((error) => {
console.log('apiError');
});
Sorry for the long title. Visually and more precise, I would like to update the stock value after a payment is made. However, I get stuck after querying the entire document (e.g. the selected one with title sneakers). Is there a way to actually query and update for example the Timberlands stock value to its value -1. Or do you have to get all data from the entire document. Then modify the desired part in javascript and update the entire document?
Here is a little snippet of a solution I came up with so far. However, this approach hurts my soul as it seems very inefficient.
const updateFirebaseStock = (orders) => {
orders.forEach( async (order) => {
try {
collRef = db.doc(`collections/${order.collectionid}`);
doc = await collRef.get();
data = doc.data();
//Here:const newItems = data.items.map(if it's corr name, update value, else just return object), results in desired new Array of objects.
//Then Update entire document by collRef.update({items: newItems})
} catch (error) {
console.error(error)
};
});
}
You don't need to get the document at all for that, all you have to do is use FieldValue.increment(), using your code as a starting point it could look like this:
collRef = db.doc(`collections/${order.collectionid}`);
collRef.update({
Price: firebase.firestore.FieldValue.increment(-1)
});
You can increment/decrement with any numeric value using that function.
I'm trying to make a MySQL query to filter data from a table. Effectively what I want to do is:
SELECT data FROM table WHERE column IN ?
The filter is coming from checkboxes in a form on a webpage, so I can pass an array or object fairly easily, but it'll be a varying number of parameters for the IN each time, so I can't us multiple ?. I tried making a for loop to make multiple queries concatenate the arrays that the queries returned, but I ran into scope issues with that. I also tried passing an array directly to the query, but that throws a syntax error. I'm sure there's a straightforward answer to this but I'm not sure how to do it.
Edit: source code added:
Here's where I'm at:
const filterShowQuery = `SELECT sl_Show.showId, sl_Band.BandName,
sl_Show.date, sl_Venue.venueName,
sl_Show.length, sl_Show.attendance, sl_Show.encore FROM sl_Show
JOIN sl_Band on sl_Show.BandID = sl_Band.BandId
JOIN sl_Venue on sl_Show.VenueId = sl_Venue.VenueId
WHERE sl_Band.BandName IN (?)
ORDER BY sl_Band.BandName;`;
Trying to get an array into the ? in WHERE sl_Band.BandName IN
const getShows = (req, res,next) =>{
var {bands, venues} = req.body;
var i = 0; //left over from previous attempt
var data = [];
for (b in bands){
mysql.pool.query(filterShowQuery, bands[b], (err, result) => {
if(err){
console.log('filter band error');
next(err);
return;
}
data = data.concat(result);
console.log(data); //data concatenates property and increases through for loop
})
// same action to be performed with venues once solved
// for (v in venues){
// conditions[i] = venues[v];
// i++;
console.log(data); //data is empty when logging from here or using in res
res.json({rows:data});
}
}
SECURITY WARNING!
I must to say: NEVER, NEVER PASS DATA DIRECTLY TO YOUR SQL!
If you don't know why, just google for SQL Injection. There are lots of examples on how it is done, how easily it can be done, and how to protect your application from this sort of attack.
You should always parametrize your queries. But in the very rare case which you really need to insert data concatenating a string into your sql, validate it before.
(E.g.) If it's a number, than use a Regex or some helper method to check if the value you are inserting into your SQL String is really and only a number and nothing else.
But aside that, you did not provide any source code, so it's really hard to give any help before you do that.
I want to return an item with a specific ID and perform an update operation on it. My query gets the right result, but it won't let me update it.
I tried following this tutorial: https://www.youtube.com/watch?v=mYyPbfpoZeM
And read the documentation. Both didn't help. Other threads to the same topic are, well, different.
I have a database of objects which have a unique ID stored as integer.
I have an HTML form to get an ID as user input and the query below to retrieve the according object.
I tried this. The query worked, the update didn't.
db.collection('objects').where('ID','==', ID ).get().then((snapshot) => {
snapshot.docs.forEach( doc => {
console.log('debug');
console.log(doc.data().ID);
})
});
I am still new to firebase and js, so please forgive me if my code is uterly wrong.
I am currently stuck with this:
db.collection('objects').where('ID','==', ID ).get().then((doc) => {
console.table(doc);
});
Which is still not working.
For the second snippet an I currently get an unlegible table in which I can't really find the object I was looking for.
How do I update a single value in a single document?
EDIT: I forgot my implementation attempts of the update function.
I tried doc.update({value:0}) inside the for loop in snippet one which yielded doc.update is not a function. Similarly for doc.data().update(...).
In the second snippet I mainly tried to see what I got returned and ran variations of the above mentioned uodate function. With no success.
I managed to get it to work by studying the part of the firestore documentation that goes more into detail about the actual functions. Somehow it was hard for me to find this.
db.collection("users").where("name", "==", somename).limit(1).get().then(query => {
console.log(query);
const thing = query.docs[0];
console.log(thing.data());
let tmp = thing.data();
tmp.current_game_play = tmp.current_game_play + 1;
console.log(tmp);
thing.ref.update(tmp);
});
So I use where to get a Query object, use get to get a a querySnapshot inside the then promise resolve, use docs[0] to retrieve the first (and only) documentSnapshot and finally ref to get a reference that makes the whole thing updatable later.
try this:
var objectRef= db.collection("objects").doc(ID);
objectRef.update({
value: 0
}).then(function() {
console.log("Document successfully updated!");
}).catch(function(error) {
// The document probably doesn't exist.
console.error("Error updating document: ", error);
});
I have been working with Firebase for a few months now and just when I think I have a good working understanding, I get thrown for a loop. I come from a SQL background, so it has been a challenge working with NoSQL.
What I am trying to achieve:
When a end user selects a category from a select menu, I need it to bring back user profile data that is related.
How my data is currently structured:
I have a collection of "userProfiles". Nested within I have a collection of categories that the user selects for themselves. Here is an image:
There can be N number of user profiles and nested categories.
The Code. Things I have tried:
at one point I had a simple $firebaseArray setup and it was working. I am not sure why isn't anymore.
Attempt #1
Please note that "category" is a uid ($id)
<!-- #ref = https://XXXX.firebaseio.com/userProfiles/-KHZmwpSwtI1GK5XyXnu/categories -->
var ref = fbRefDataService.userProfiles.orderByChild("categories").equalTo(category);
var fbArray = $firebaseArray(ref).$loaded(); // I have treid with loaded and without
$scope.userData = fbArray;
Attempt #2
var ref = fbRefDataService.userProfiles;
ref.orderByChild("categories").equalTo(category).on("value", (snapshot) => {
snapshot.forEach(function(childSnapshot) {
console.log(childSnapshot.val());
});
});
Attempt 3
var qProfile = $q.defer();
var ref = fbRefDataService.userProfiles.child("categories");
ref.orderByChild("$id").equalTo(category).on("value", function(snapshot) {
qProfile.resolve(snapshot.val());
}, function(errorObject) {
qProfile.reject(errorObject);
});
return qProfile.promise;
I have been at this for days now. Exhausted all my known options. I am sure I am missing something simple.
I would be very greatful to anyone who could tell me what I am doing wrong, or point me in the right direction to be able to get user data by category.
Last notes:
I am using Ionic 1.3 and AngularJS 1.5.5
Thanks so much for any help.
So I finally found a solution to my problem. Knowing you can't use .equalTo() on a nested collection, I had it working with an earlier version. So I couldn't let go of trying to achieve the same result. It really must have been some edge case...
So my solution (and it is not the best one) was to load all my user data and then use my friend underscore in the Controller and custom angular filters in the VM to get the collection of data I needed.
I am just building a prototype so I needed something, anything to hack it together.
Here is the working code (Still a work in progress):
function categoryChanged(category) {
if (!category) return null;
function filterCategory(data, key) {
var findMatch = [];
_.each(data.categories, function(value) {
if (value.name === category.name) {
if (data.length !== 0) {
findMatch = data;
}
}
});
return findMatch;
};
var ref = fbRefDataService.userProfiles;
ref.orderByChild("categories").on("value", (snapshot) => {
var findMatch = _.map(snapshot.val(), filterCategory);
vm.userProfileData = findMatch;
});
}
Well, I hope this helps any other stubborn programmers out there. All the best.