VueJS Firebase Syntax error - firebase

I cannot find the syntax error in this signup method. It's been more than an hour now.
.then(() => {
db.collection("users").doc(this.slug).get().then((doc) => {
let data = doc.data()
db.collection("users").doc(cred.user.uid).set(data).then({
db.collection("users").doc(this.slug).delete()
})
})
})
This code above basically gets the newly created document, then puts the data into let data. After that, it creates a new document with the User UID as the name passes the data to it and then just deletes the old document. A syntax error lies in that code, but the indicator says, it is the dot between db and collection (db.collection)
Error report
methods: {
signup(){
console.log('signup ran')
if(this.heroName){
this.slug = slugify(this.heroName, {
replacement: '-',
remove: /[$*_+~.()'"!\-:#]/g,
lower: true
})
console.log(this.slug)
let ref = db.collection('users').doc(this.slug)
ref.get().then(doc => {
if(doc.exists){
this.feedback = 'This alias already exists'
} else {
// this alias does not yet exists in the db
this.feedback = 'This alias is free to use'
firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
.then(cred => {
ref.set({
alias: this.heroName,
user_id: cred.user.uid,
gemcount: 15
})
// FIXME: error below
.then(() => {
db.collection("users").doc(this.slug).get().then((doc) => {
let data = doc.data()
db.collection("users").doc(cred.user.uid).set(data).then({
db.collection("users").doc(this.slug).delete()
})
})
})
.then(() => {
this.$router.push({ name: 'Core' })
})
})
.catch(err => {
console.log(err)
this.feedback = err.message;
})
}
})
} else {
this.feedback = 'Please enter a heroName'
}
}
}

db.collection("users").doc(cred.user.uid).set(data).then({
db.collection("users").doc(this.slug).delete()
})
then expect its parameter to be a function, I reckon it where your error come from, the correct should be:
db.collection("users").doc(cred.user.uid).set(data).then(() => {
db.collection("users").doc(this.slug).delete()
})

Related

Firestore vuejs chained calls stop

I've been studying the tutorial on https://savvyapps.com/blog/definitive-guide-building-web-app-vuejs-firebase. The following piece of code was not properly working for me.
signup() {
fb.auth.createUserWithEmailAndPassword(this.signupForm.email, this.signupForm.password).then(user => {
this.$store.commit('setCurrentUser', user)
// create user obj
fb.usersCollection.doc(user.uid).set({
name: this.signupForm.name,
title: this.signupForm.title
}).then(() => {
this.$store.dispatch('fetchUserProfile')
this.$router.push('/dashboard')
}).catch(err => {
console.log(err)
})
}).catch(err => {
console.log(err)
})
}
Could anyone help me?
P.S: After lots of research, I've stumbled upon that by this way I got the document created but the code inside then is not working yet. This change was based on Doug Stevenson's video on youtube about promises.
const promise = fb.usersCollection.doc(user.user.uid).set({
name: this.signupForm.name,
title: this.signupForm.title
})
return promise.then(() => {
console.log('set ok')
this.$store.dispatch('fetchUserProfile')
this.performingRequest = false
this.$router.push('/dashboard')
}).catch(err => {
this.performingRequest = false
console.log(err)
this.errorMsg = err.message
})
P.S 2: The line of code below helps to get the document created:
firebase.firestore().settings({ experimentalForceLongPolling: true })
Tylerhan has answered the question on github. Here is the solution:
async signup () {
this.performingRequest = true
await fb.auth.createUserWithEmailAndPassword(this.signupForm.email, this.signupForm.password).then(user => {
this.$store.commit('setCurrentUser', user.user)
})
const user = this.$store.getters.getCurrentUser
const userProfile = {
name: this.signupForm.name,
title: this.signupForm.title
}
fb.usersCollection.doc(user.uid).set(userProfile).then(() => {
this.$store.dispatch('fetchUserProfile')
this.performingRequest = false
this.$router.push('/dashboard')
}).catch(err => {
this.performingRequest = false
console.log(err)
this.errorMsg = err.message
})
}

vuexfire firestoreAction, binding with arg

I'm trying to bind my module's store to a document
import Vue from 'vue'
import { db } from '../my-firebase/db'
import { firestoreAction } from 'vuexfire'
export const user = {
...
actions: {
logOutUser: ({ commit }) => {
commit('logOutUser')
},
logInUser: ({ dispatch, commit }, userInfo) => {
let dbRef = db.collection('users').doc(userInfo.uid)
dbRef.update({ authInfo: userInfo })
.then(() => {
commit('logInUser', userInfo)
})
dispatch('bindFirebaseUser', dbRef)
},
bindFirebaseUser: (context, userRef) => {
console.log('Running dispatch BindFirebaseUser')
return firestoreAction(({ bindFirestoreRef }) => {
// return the promise returned by `bindFirestoreRef`
console.log('userRef:')
console.log(userRef)
return bindFirestoreRef('firebaseData', userRef)
})
}
}
}
It's not working. How do I bindFirestoreRef with the argument userRef? It doesn't seem to bind, though I can write to the firestore properly, so I would assume that my db is set up correctly.
It just doesn't give any form of error whatsoever, but if it binds, it should populate my store with the data I wrong shouldn't it?
You can pass the reference as the second argument to firestoreAction
bindFirebaseUser: firestoreAction(({ bindFirestoreRef }, userRef) => {
return bindFirestoreRef('firebaseData', userRef)
})

Add Firebase image URL to my collection

I have the following method I'm accessing when my VueJS component is loading:
getServices () {
fb.servicesCollection.get().then(querySnapshot => {
this.serviceList = []
querySnapshot.forEach(doc => {
const { name, icon } = doc.data()
fb.storage.ref().child(icon).getDownloadURL().then(function (url) {
console.log(url)
})
this.serviceList.push({id: doc.id, name: name, icon: 'iconURL'})
})
this.isLoading = false
}).catch(error => {
console.log(error)
})
}
What I want to achieve is to get the url to replace the current 'iconURL' string. Didn't find any method to do that in the last couple of hours. Please help!
The following should do the trick. (However note that I could no test it, so it may need a bit of fine tuning... You can report how it works in the comments and we correct it if necessary)
Since you want to execute several getDownloadURL() asynchronous calls to Firebase Storage in parallel, you have to use Promise.all(), since getDownloadURL() returns a promise, see the doc.
getServices () {
let namesArray = []
let docIdArray = []
fb.servicesCollection.get().then(querySnapshot => {
this.serviceList = []
let promises = []
querySnapshot.forEach(doc => {
const icon = doc.data().icon;
promises.push(fb.storage.ref().child(icon).getDownloadURL())
namesArray.push(doc.data().name)
docIdArray.push(doc.id)
})
return Promise.all(promises)
})
.then(results => {
results.forEach((value, index) => {
this.serviceList.push({id: docIdArray[index], name: namesArray[index], icon: value})
})
})
}).catch(error => {
console.log(error)
})
}
This is how I got it in the end...
getServices () {
fb.servicesCollection.get().then(querySnapshot => {
this.serviceList = []
querySnapshot.forEach(doc => {
const { name, icon } = doc.data()
fb.storage.ref(icon).getDownloadURL().then(url => {
this.serviceList.push({id: doc.id, name: name, icon: url})
})
})
this.isLoading = false
}).catch(error => {
console.log(error)
})
}
Thank you for all your efforts to help me!!! Highly appreciate it!

Observable from 2 promises

I think my solution is in this question but I can't get it to work Promise.all behavior with RxJS Observables?
I'm trying to return an observable on two promises via forkJoin.
One promise gets an ID from the server and another processes a file to generate a thumbnail.
export function createSceneFromFile(action$) {
return action$.ofType(CREATE_SCENE_FROM_FILE)
.mergeMap(({locationId,file}) =>
createSceneThumb(locationId,file)
.map((res,preview) => {
console.log(res,preview)
if (res.error) {
return { type: CREATE_SCENE_FAILED, payload: res.message }
} else {
return {type: CREATE_SCENE_SUCCESS, payload: {...res.payload,preview} }
}
})
.catch(err => { return { type: CREATE_SCENE_FAILED, message: err } })
)
}
function createSceneThumb(locationId,file){
const request = fetch(`${API_URL}/location/${locationId}/createscene/${file.name}/`, {
method: 'get',
credentials: 'include',
}).then(res => res.json())
const thumb = fileToScenePreview(file)
return Observable.forkJoin(request,thumb)
}
export function fileToScenePreview(file){
return new Promise((resolve,reject)=>{
getFileThumb(file).then((canvas)=> {
canvas.toBlob((blob) => {
blob.lastModifiedDate = new Date()
blob.name = 'scenepreview_' + file.name + '.png'
const uploader = new S3Upload({
getSignedUrl: getSignedUrl,
uploadRequestHeaders: {'x-amz-acl': 'public-read'},
contentType: 'image/png',
scrubFilename: (filename) => filename.replace(/[^\w\d_\-.]+/ig, ''),
contentDisposition: 'auto',
s3path: 'assets/',
onError:()=>reject,
onFinishS3Put: ()=>resolve(blob.name),
})
uploader.uploadFile(blob)
})
})
})
}
But i never get a response.
Is this the right way of going about it?

TypeError: Cannot set property 'words' of undefined

I have this action in my vuex store:
loadExercises ({commit}) {
commit('setLoading', true)
const db = firebase.firestore()
db.collection('exercises').get()
.then(querySnapshot => {
const exercises = []
querySnapshot.forEach((doc) => {
exercises.push({
title: doc.data().title,
language: doc.data().language,
translated: doc.data().translated,
lastOpen: doc.data().lastOpen,
dueDate: doc.data().dueDate,
uid: doc.data().uid,
userId: doc.data().userId,
words: [{ word: '', uid: '', translation: '' }]
})
db.collection('exercises').doc(doc.data().uid).collection('words').get()
.then(words => {
const wordsArray = []
words.forEach(word => {
wordsArray.push(word.data())
})
let exercise = this.getters.loadedExercise(doc.data().uid)
exercise.words = wordsArray
})
.catch(error => {
commit('setLoading', false)
console.log(error)
})
})
commit('setLoading', false)
commit('setLoadedExercises', exercises)
})
.catch(error => {
commit('setLoading', false)
console.log(error)
})
}
It is supposed to fetch exercises from a firebase cloudstore db. It works on some routes but not all.
When using these two getters it works:
loadedExercises (state) {
return state.loadedExercises
},
loadedExercise (state) {
return (exerciseId) => {
return state.loadedExercises.find(exercise => {
return exercise.uid === exerciseId
})
}
}
But when I use these getters:
upcomingExercises (state, getters) {
return getters.loadedExercises.filter(exercise => {
return exercise.dueDate > 0
})
},
latestExercises (state, getters) {
return getters.loadedExercises.splice(0, 5)
},
it does not work I just get "TypeError: Cannot set property 'words' of undefined". What is it that I do wrong?
It looks to me like you aren't returning the values back to the function.
Try replacing
db.collection('exercises').get()
with
return db.collection('exercises').get()
and
db.collection('exercises').doc(doc.data().uid).collection('words').get()
with
return db.collection('exercises').doc(doc.data().uid).collection('words').get()

Resources