Trying to remove an item from the firebase array using arrayRemove but I'm getting the following error:
ReferenceError: Can't find variable: FieldValue
const removeItemHandler = () => {
//this logs the array item like is should, dont think this value is the issue
console.log(props.item)
console.log(props.currentNote)
//removes note from the notes array
db.collection('users').doc(userEmail)
.collection('books').doc(props.currentBook)
.collection('specific').doc(props.currentNote).update({
notes: FieldValue.arrayRemove(props.item)
})
showRemoveButton(false)
}
I was following the example linked below, really not sure why my, very similar situation is giving me this error. Thank you!
https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html
also, keep in mind that props.item is referencing the array items name, I checked the type and the value with the console.log's and it is correct. Confident that is not part of the issue.
You are accessing FieldValue which is undefined. You cannot access it directly.
You can access it via firebase.firestore.FieldValue or if you imported firestore directly then firestore.FieldValue. So change your code like this :
const removeItemHandler = () => {
//this logs the array item like is should, dont think this value is the issue
console.log(props.item)
console.log(props.currentNote)
//removes note from the notes array
db.collection('users').doc(userEmail)
.collection('books').doc(props.currentBook)
.collection('specific').doc(props.currentNote).update({
notes: firebase.firestore.FieldValue.arrayRemove(props.item)
notes: firestore.FieldValue.arrayRemove(props.item) // or if you are imported firestore
})
showRemoveButton(false)
}
Related
This is definitely a newbie question, and in part answered in the Firebase documentation, but for the life of me it's not working when implementing it in my own code - so I'm hoping the community can help me understand what I am doing wrong, and how to fix it.
When getting documents from Firestore, I can't access the actual values within, due to its structure, so when setting e.g. "var name = doc.name" it just gives me undefined. For getting MULTIPLE documents, I've already found apiece of code that works:
// Getting the document
docRef.collection(collectionRef).get()
.then((snapshots) => cleanData(snapshots))
.then((items) => items.map((item) => sampleFunction(item)));
// Firebase Utility cleaning documents (array)
function cleanData(snapshots) {
let data = [];
snapshots.forEach(function(doc) {
data.push({
id: doc.id,
...doc.data()
});
});
return data;
}
But when using this piece of code with e.g. collection("x").doc("id"), then it throws the error:
"Uncaught (in promise) TypeError: snapshots.forEach is not a function"
So I went ahead to modify the function as follows:
// Firebase Utility cleaning document (single)
function cleanDoc(snap) {
let data = [];
data.push({
id: doc.id,
...doc.data()
});
return data;
}
But that gives me "undefined" when attempting to access the values in my function again...
The documentation (in the city example) says to define a class. When I did that, I was able to get values from one document, but it gave me undefined the second time I called the same function on one page.
For context, I'm trying to display a User Profile, which displays people they work with on a project, which means I call these profiles as well, the data structure just callsa reference to the "worked with" profiles, and I get their ID's just fine, but when attempting to render an HTML item for each, the values within their profiles are undefined....Its confusing the hell out of me anyways.
If your function is an async function:
collectionSnap = await docRef.collection(collectionRef).get();
val items=[]
await Promise.all(querySnap.docs.map(async (doc) => {
// Do your your work and populate items
}));
// Do your work with items
You can try this approach to processing your documents.
I want to retrieve data from api and assign it to some value inside the angular component. In subscribe I'm trying to assign the data to loggedUser and then call function inside this subscribe to navigate to another component with this received object. Unfortunately I got the error : The requested path contains undefined segment at index 1. I want to have this object set outside the subscribe too. How can I achieve this?
logIn() {
this.portfolioAppService.logIn(this.loggingUser).subscribe((data) => {
this.loggedUser = data;
console.log(this.loggedUser);
console.log(data);
this.navigateToProfile(this.loggedUser.Id);
});
}
navigateToProfile(id: number) {
this.router.navigate(['/profile', id]);
}
console output
You are using an incorrectly named property when calling navigateToProfile.
From your console output, I can see that the data object in the subscribe looks like this:
{
id: 35,
// ..
}
But you are calling the function like this:
this.navigateToProfile(this.loggedUser.Id);
Instead, use the property id (lower case)
this.navigateToProfile(this.loggedUser.id);
To narrow this problem down in the future, try being more specific in your testing. Humans are good at seeing what they want to see and will assume the problem is more complicated than it is. If you had tried console.log(this.loggedUser.Id), you would have seen the result undefined, and worked out the problem yourself.
No matter what I do I can't seem to figure out a way to access the child "onSite", which shows as being there when I log snapshot.val(), but I cannot figure out how to access it.
Code:
firebase.database().ref().child("users").orderByChild('facebook_id').equalTo(fbID).once("value").then(function(snapshot) {
console.log(snapshot.val());
console.log(snapshot.child("onSite").val());
});
Here is the response:
It shouldn't be null, it should be false. I can't do child("4mUUjF...").child("onSite").val() because I don't know what the ID is before the query. Using an each loop doesn't work, it only loops through the first level, which is the ID.
Use the key of the object
Get the snapshot val and then find the key with the Object.keys method. This will allow you to then get inside the snap. Once there it's a simple matter of accessing the values like any other object.
firebase.database().ref().child("users").orderByChild('facebook_id').equalTo(fbID).once("value").then(function(snapshot) {
let snap = snapshot.val();
let key = Object.keys(snap)[0]
console.log(snap[key].onSite);
})
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
Your code needs to handle the list, by using Snapshot.forEach():
firebase.database().ref().child("users").orderByChild('facebook_id').equalTo(fbID)
.once("value").then(function(result) {
result.forEach(function(snapshot) {
console.log(snapshot.val());
console.log(snapshot.child("onSite").val());
});
});
I went through docs, github repositories but nothing worked for me yet.
My datastructure:
App {
posts : {
<post_keys> : {
auth_name : "name",
text : "some text" //and many other fields
}
}
}
1) Github repository : If I use this, I only get one field from one function, if I need all the fields, I would need to write separate functions for each, which is a bad approach.
2) Algolia Official Docs for Node.js : This cannot be deployed as a cloud function, but it does what I intend to do.
How can I write a function that can be deployed on Firebase and gets the whole object indexed with its key in Algolia?
Okay so I went ahead to create a Firebase Cloud function in order to index all objects in the Algolia index. This is the solution:
What you were doing is something like this:
exports.indexentry = functions.database.ref('/blog-posts/{blogid}/text').onWrite(event => {
What you should do is the following:
exports.indexentry = functions.database.ref('/blog-posts/{blogid}').onWrite(event => {
const index = client.initIndex(ALGOLIA_POSTS_INDEX_NAME);
var firebaseObject = event.data.val();
firebaseObject.objectID = event.params.blogid;
return index.saveObject(firebaseObject).then(
() => event.data.adminRef.parent.child('last_index_timestamp').set(
Date.parse(event.timestamp)));
});
The difference is in the first line: In the first case, you only listen to text changes, hence you only get the data containing the text change.
In the second case, you get the whole object since you listen to changes in all of the blog object (notice how /text was removed).
I tested it and it works for me: whole object including author was indexed in Algolia.
I have something like the following code:
User.findOne(id)
.exec((err, user) => {
Pets.find(_.pluck(user.pets, 'id'))
.populate("toys")
.exec((err, petsWithToys) => {
user.pets = petsWithToys;
return res.ok({ user: user });
});
});
When I look at the response in the client I don't see the toys array inside the pet.
I thought maybe this was due to overriding the toJSON function in my User model but even when removing it I get the same behavior.
Also, I've found out that if I assign the values to a new property that is not defined in the model, I do see the values at the client. I.e. if I do
user.petsNew = petsWithToys;
I will see the fully populated property.
I've seen the documentation of toObject where is says it removes instance methods (here) but I am not sure why the collection is considered a method and don't understand how after changing the value it is still removed.
Any comments/explanations/workarounds?
P.S. Tried to step through the code but can't step into toObject...
Add user = user.toJSON(); before user.pets = petsWithToys;
Check https://stackoverflow.com/a/43500017/1435132