Reputation: 1757
I am attempting to configure a Vue.js app to add additional data to an already-created user in Firebase. I have set up SignUp.vue to set initial input, including the email, password, and name using:
ref.set({
name: this.name,
email: this.email,
user_id: cred.user.uid
})
In Home.vue, I included an input field with the following method to add the input to the currently-logged in user in the database:
async addInput () {
let ref = await db.collection('users')
ref.where('user_id', '==', firebase.auth().currentUser.uid).add({
newInput: this.newInput
})
}
However, this still did not work. Any recommendations on how to add input to an existing user?
See full code below:
SignUp.vue
<template>
<div class="sign-up">
<p>Let's create a new account!</p>
<input type="text" v-model="email" placeholder="Email" />
<br />
<input type="password" v-model="password" placeholder="Password" />
<br />
<input type="text" v-model="name" placeholder="Name" />
<br />
<v-btn @click="signUp" color="info">Sign Up</v-btn>
<span>
or go back to
<router-link to="/login">login</router-link>.
</span>
</div>
</template>
<script>
import slugify from "slugify";
import firebase from "firebase";
import db from "@/firebase/init";
export default {
name: "signUp",
data() {
return {
email: "",
password: "",
name: ""
};
},
methods: {
signUp() {
if (this.name && this.email && this.password) {
this.slug = slugify(this.name, {
replacement: "-",
remove: /[$*_+~,()'"!\-:@]/g,
lower: true
});
let ref = db.collection("users").doc(this.slug);
ref.get().then(doc => {
if (doc.exists) {
this.feedback = "This alias already exists";
} else {
firebase
.auth()
.createUserWithEmailAndPassword(this.email, this.password)
.then(cred => {
ref.set({
name: this.name,
email: this.email,
user_id: cred.user.uid
});
})
.then(() => {
this.$router.push({ name: "Home" });
})
.catch(err => {
this.feedback = err.message;
});
this.feedback = "This alias is free to use";
}
});
} else {
this.feedback = "You must enter all fields";
}
}
}
};
</script>
Home.vue
<template lang="html">
<div class="editProfile container">
<v-app id="inspire">
<v-container fluid>
<h1>Update Your Profile!</h1>
<v-card max-width="344" class="mx-auto">
<v-card-title>New User Input</v-card-title>
<v-text-field v-model="newInput"></v-text-field>
<v-card-actions>
<v-btn text @click="addInput()">Click</v-btn>
</v-card-actions>
<v-list class="elevation-1">
<v-list-tile-content v-for="user in this.$store.getters.getUsers" :key="user.id" >
<v-list-tile>
<textarea v-model="user.newInput" readonly></textarea>
</v-list-tile>
</v-list-tile-content>
</v-list>
</v-card>
</v-container>
</v-app>
</div>
</template>
<script>
import firebase from "firebase";
import db from "@/firebase/init";
export default {
name: "home",
beforeCreate: function() {
this.$store.dispatch("setCurrentUser");
},
data: () => ({
currentlyEditing: null,
newInput: null
}),
methods: {
async addInput() {
let ref = await db.collection("users");
ref.where("user_id", "==", firebase.auth().currentUser.uid).add({
newInput: this.newInput
});
}
}
};
</script>
Store.js
import Vue from 'vue'
import Vuex from 'vuex'
import firebase from 'firebase'
import db from '@/firebase/init'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
users: null
},
getters: {
getUsers: state => {
return state.users
}
},
mutations: {
setCurrentUser: state => {
const users = []
let ref = db.collection('users')
ref.where('user_id', '==', firebase.auth().currentUser.uid).get()
.then(snapshot => {
snapshot.forEach(doc => {
let currentUserData = doc.data()
currentUserData.id = doc.id
users.push(currentUserData)
})
state.users = users
})
}
},
actions: {
setCurrentUser: context => {
context.commit('setCurrentUser')
}
}
})
Upvotes: 1
Views: 2111
Reputation: 1757
OK, this is ultimately what I was trying to achieve, based on Augusto's feedback. This function pushes user input into an array in Firebase, which is what I am aiming for. However, I want to re-style the output, which currently returns the array container as well to the screen. How can I re-style this so that the items in the array are arranged nicely in line items without the array container? Preferably with Vuetify. Thanks!
async addInput () {
let finalInput = this.newInput
let ref = await db.collection('users').where('user_id', '==', firebase.auth().currentUser.uid)
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
doc.ref.update({'events': firebase.firestore.FieldValue.arrayUnion(finalInput)})
})
})
.catch(function(error) {
console.log("Error getting documents: ", error);
});
}
<v-list class="elevation-1">
<v-list-tile-content v-for="user in this.$store.getters.getUsers" :key="user.id" >
<v-list-tile>
{{ user.events }}
</v-list-tile>
</v-list-tile-content>
</v-list>
Upvotes: 2
Reputation: 4243
Just use update
instead add
. It's definitely will works.
async addInput () {
this.updates.push(this.newInput)
let finalInput = this.updates
let ref = await db.collection('users').where('user_id', '==', firebase.auth().currentUser.uid)
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
doc.ref.update({'newInput': finalInput})
})
})
.catch(function(error) {
console.log("Error getting documents: ", error);
});
}
Upvotes: 1