1

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')
        }
    }
})
2
  • You want append a attribute to a document? Commented Sep 5, 2019 at 17:04
  • Yes, essentially adding additional data to an existing document. Commented Sep 5, 2019 at 17:09

2 Answers 2

2

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>
Sign up to request clarification or add additional context in comments.

Comments

1

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

7 Comments

I just tried this. Error was returned in the console saying that ref.update () is not a function
What is the return type of db.collection('users').where('user_id', '==', firebase.auth().currentUser.uid) ?
Not sure what you mean by return type, what would this look like?
Just to be clear, newInput does not get set as data in SignUp.vue. My goal is to input this into the doc after the user has been created.
I understand your problem, you must get the reference's document from your query and use .update() method to do it. The problem is that I don't know what object is returned from where method. But, to use update you must a DocumentReference. The where can return a List of DocumentReference so you can take the first element and use update on the sintax that I wrote.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.