Javascript subscription result children lists are undefined - javascript

In my dashboard application I have the following data structure:
Project -> Dashboard -> etc. .So this means a project object inherits a list of dashboard objects. When the user logs in the project data get loaded and observed so that different components can access the project data. But now when I am trying to access a specific dashboard of a project in my subscription I am getting an undefined error. My subscription looks as follows:
ngOnInit(): void {
this.dataService.projectData
.subscribe((project: Project) => {
this.project = project;
console.log('Project', project);
let d: Dashboard = project.dashboards[0];
this.currentDashboardId = project.dashboards[0].id;
this.dataService.changeCurrentDashboardId(this.currentDashboardId);
this.currentSheetId = project.dashboards.find(x => x.id === this.currentDashboardId).sheets[0].id;
this.dataloaded = true;
});
}
The printed log 'Project' even displays the object correctly. But one line later when accessing a dashboard I am getting undefined. Can't explain why. Maybe anybody of you guys know and can tell me why. I appreciate that. Thanks in advance.

Use first() operator to be sure that the data revived, console.log is a bit tricky, it's not show what happened in correct time,
your code can be like:
this.dataService.projectData
.pipe(first())
.subscribe((project: Project) => {
// your code is here
});
you can use Filter() as well to wait for specific value in your response
something like
this.dataService.projectData
.pipe(filter(project) => project.somevalue !== undefined)
.subscribe((project: Project) => {
// your code is here
});

Related

Getting values from single Firebase Firestore Document

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.

Could Not find Variable FieldValue, React Native/Firebase

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)
}

Mongoose save() not saving changes

I have a fully functioning CRUD app that I'm building some additional functionality for. The new functionality allows users to make changes to a list of vendors. They can add new vendors, update them and delete them. The add and delete seem to be working just fine, but updating doesn't seem to be working even though it follows a similar method I use in the existing CRUD functionality elsewhere in the app. Here's my code:
// async function from AXIOS request
const { original, updatedVendor } = req.body;
let list = await Vendor.findOne({ id: 1 });
if (!list) return res.status(500).json({ msg: 'Vendors not found' });
let indexOfUpdate = list.vendors.findIndex(
(element) => element.id === original.id
);
list.vendors[indexOfUpdate].id = updatedVendor.id;
list.vendors[indexOfUpdate].name = updatedVendor.name;
const updated = await list.save();
res.json(updated);
The save() isn't updating the existing document on the DB side. I've console logged that the list.vendors array of objects is, indeed, being changed, but save() isn't doing the saving.
EDIT:
A note on the manner of using save, this format doesn't work either:
list.save().then(res.json(list));
EDIT 2:
To answer the questions about seeing the logs, I cannot post the full console.log(list.vendors) as it contains private information, however, I can confirm that the change made to the list is showing up when I run the following in the VendorSchema:
VendorSchema.post('save', function () {
console.log(util.inspect(this, { maxArrayLength: null }));
});
However, the save still isn't changing the DB side.
Since you are using nested objects, Mongoose will not be able to detect the changes made. You need to mark the modified as an object before the save
list.markModified('vendors');

Angular Http subscribe - cannot assign to variable in component

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.

Get firebase data (with or without vuefire) using a parameter from router before DOM renders in Vuejs?

I am navigating into a view from another view and passing the itemdId as param value to vue router.
I want to be able to call firebase with that itemId so that I can filter the data and the filtered result/data is used in the UI. I am using vuefire.
What is happening is that vue starts rendering before the data is available in created() and I see error is the console saying view is referring to undefined property values.
Is there a way to render the view after the data is available?
I have tried the using beforeMount as well as created and beforeCreate approaches.
See code below:
<h1>{{projects[0].project_name}}</h1> //it says type error. cannot read property project_name of undefined. Sometimes on refresh it works but most times it does not.
Script code below:
let projectsRef = db.ref('projects');
export default {
name: 'ProjectDetailsOpenInvesting',
props: {
data: Object
},
firebase:{
projects: projectsRef
},
data(){
return {
projects:[],
.....
}
},
created(){
var that = this;
console.log(this.$route.params.itemid) //this works
this.projects = this.projects.filter(function(p){
return p.project_id == that.$route.params.itemid //this works as well
})
}
Firebase screenshot here
As you have mentioned, one approach is to fetch after navigation, i.e. fetch the data in the component's created hook.
To do that with vuefire you need to programatically bind the Realtime Database projectsRef Reference to the projects property in your Vue application, as follows:
created(){
console.log(this.$route.params.itemid)
const itemId = this.$route.params.itemid;
this.$rtdbBind('projects', projectsRef.orderByKey().equalTo(itemId)).then(projects => {
this.projects === projects;
});
}
As explained in the API doc:
$rtdbBind returns a Promise that is resolved once the data has been
retrieved and synced into the state.
Note that you need to install the rtdbPlugin plugin: https://vuefire.vuejs.org/api/vuefire.html#rtdbplugin
Also note that instead of filtering the desired project item in the front-end (with filter(function(p){return p.project_id == that.$route.params.itemid}))), we filter it in the back-end, at the level of the database (projectsRef.orderByKey().equalTo(itemId)) which is more efficient and which avoids transmitting the entire set of objects from the back-end to the front-end (and avoids paying for this downloaded volume, see https://firebase.google.com/pricing?authuser=0).

Categories