skip to Main Content

I am trying to make a chat where at the top of each message it displays the user’s name on the top of each document they add when they send each message but I am unable to get the single field without the rest of the document.

<script>
import { projectFirestore } from '../Firebase/Config'
import { firebaseAuth } from "../Firebase/firebase";
import getChat from "../Composables/getChat";
import { ref } from 'vue'
import { timestamp } from '../Firebase/Config'
import getPSubscribed from '../Composables/getPremium'
export default {


  setup(){
    const {  PSubscribed, load2 } = getPSubscribed(firebaseAuth.currentUser.uid);
    load2()
      const { Chat, error, load } = getChat();
      load();
    const name = PSubscribed.Username
    const message = ref('')
    const Activate = ref(false)
    const handleSubmit = async () => {  
    const NewChat = {
        name: name.value,
        message: message.value,
        createdAt: timestamp(),
    }
    const res = await projectFirestore.collection('Subscribed').doc(firebaseAuth.currentUser.uid).collection('messages').add(NewChat)
  }
  return { handleSubmit, Activate, message, Chat, load, load2, PSubscribed, name }
}
}
    </script>

    <template>
      <div class="chat-window">
        <div class="grid grid-cols-1 justify-items-center gap-y-2">
        <div v-for =" doc in Chat" :key="doc.id" class="rounded-xl bg-red-100 w-max md:w-1/3 lg:w1/3 xl:w-1/5 2xl:w-1/5">
            <p class="font-bold">{{ doc.name }}</p><br>
            <p class="text-left mx-4">{{ doc.message }}</p>
            <p class="created-at">{{ doc.createdAt.toDate() }}</p>
          </div><br><br>
        </div>
          <form @submit.prevent="handleSubmit">
      <textarea class="w-max md:w-2/3 lg:w-2/3 xl:w-2/5 2xl:w-3/5 p-10 rounded-xl outline-none"
        placeholder="Type a message and hit enter to send..." 
        v-model="message"
      ></textarea><br>
      <button @click="Loading = true" class="bg-neutral-800 hover:bg-neutral-900 active:bg-neutral-800 text-red-700 hover:text-neutral-400 hover:scale-105 text-xl w-64 p-4 rounded-xl shadow cursor-pointer inline-block m-10 transition ease-in-out duration-300 drop-shadow-2xl"
      >{{ Loading ? "Sending..." : "Send" }}</button>
      <div v-if="error" class="error">{{ error }}</div>
    </form>
        </div>

    </template>

Above is the page where I want to display the messages and below is where I get PSubscribed from and the document which belongs to this user.

import { projectFirestore } from "../Firebase/Config";
import { ref } from "vue"

const getPSubscribed = (id) => {
    const PSubscribed = ref(null)
    const error = ref(null)

    const load2 = async () => {
        try{
            let res = await projectFirestore.collection('Subscribed').doc(id).get()

            if(!res.exists) {
                throw Error('That Profile no longer exists')
            }

            PSubscribed.value = {...res.data(), id: res.id}
              // console.log(PSubscribed.value)
            
        }
        catch (err){
            error.value = err.message
            console.log(error.value)
        }
    }

    return { PSubscribed, error, load2}
}

export default getPSubscribed

Does anyone know how to get PSubscribed’s Username field and add it under name value?

2

Answers


  1. Chosen as BEST ANSWER

    An alternate way I found to do this is by adding a displayName with firebase Auth on the Signup page like below.

    <script>
    import { ref } from 'vue'
    import { useRouter } from 'vue-router'
    import useSignup from '../Composables/useSignup'
    
    export default {
        setup() {
        const { error, signup } = useSignup()
        const Recemail = ref('')
        const Password = ref('')
        const displayName = ref('')
        const router = useRouter()
        const Loading = ref(false)
    
        const createProfile = async () => {
        await signup(Recemail.value, Password.value, displayName.value )
          console.log('user signed up')
          router.push({ name: 'Signuppremium' })
        }
        return { Recemail, Password, createProfile, Loading, displayName }
        
    }}
    </script>
    <template>
      
      <form @submit.prevent="createProfile"><br><br>
        <p class="text-5xl text-red-700 font-serif">Signup</p><br><br>
        <input v-model="displayName" required type="text" placeholder="Display Name for Chat" class="h-8 w-fit bg-neutral-300 active:bg-neutral-500 focus:bg-neutral-500 rounded shadow"><br><br>
        <input v-model="Password" required type="password" placeholder="Password" class="h-8 w-fit bg-neutral-300 active:bg-neutral-500 focus:bg-neutral-500 rounded shadow"><br><br>
        <input v-model="Recemail" required type="email" placeholder="Email for login puposes" class="h-8 w-fit bg-neutral-300 active:bg-neutral-500 focus:bg-neutral-500 rounded shadow"><br><br>
    
      <button @click="Loading = true" class="bg-neutral-800 hover:bg-neutral-900 active:bg-neutral-800 text-red-700 hover:text-neutral-400 hover:scale-105 text-xl w-64 p-4 rounded-xl shadow cursor-pointer inline-block m-10 transition ease-in-out duration-300 drop-shadow-2xl"
                >{{ Loading ? "Loading..." : "Next" }}</button>
      </form>
    
    </template>
    

    It is important to note displayName can't just be any value you put firebase only has a certain amount of objects it allows displayName is one of them so I would use this.

    Here is my signup composable adding the displayName with updateProfile function

    import { ref } from 'vue';
    import { projectAuth } from '../Firebase/Config';
    
    // refs & signup outside of exported function
    // they don't need to be re-created every time we invoke useSignup
    const error = ref(null);
    
    const signup = async (Recemail, Password, displayName) => {
      error.value = null
    
      try {
        const res = await projectAuth.createUserWithEmailAndPassword(Recemail, Password)
        if (!res) {
          throw new Error('Could not complete signup')
        }
        await res.user.updateProfile({ displayName })
        error.value = null;
        console.log( res.user )
        return res
      }
      catch(err) {
        console.log(err.message)
        error.value = err.message;
      }
    }
    
    const useSignup = () => {
      return { error, signup }
    }
    
    export default useSignup
    

    Now I am able to bring the displayName to add at the top of each of my chat messages through firebaseauth.

    <script>
    import { projectFirestore } from '../Firebase/Config'
    import { firebaseAuth } from "../Firebase/firebase";
    import getChatMess from "../Composables/getChatMess";
    import { ref } from 'vue'
    import { timestamp } from '../Firebase/Config'
    import getUser from '../Composables/getUser'
    export default {
    
    
      setup(){
    
          const { ChatMess, error } = getChatMess(firebaseAuth.currentUser.uid);
       
        const { user } = getUser()
        const message = ref('')
        const Activate = ref(false)
        const handleSubmit = async () => {  
        const NewChat = {
            name: user.value.displayName,
            message: message.value,
            createdAt: timestamp(),
        } 
        message.value = ''
        const res = await projectFirestore.collection('Subscribed').doc(firebaseAuth.currentUser.uid).collection('messages').add(NewChat)
      }
    
      return { handleSubmit, Activate, message, ChatMess }
    }
    }
        </script>
    
        <template>
          <div class="chat-window">
            <div class="grid grid-cols-1 justify-items-center gap-y-2">
            <div v-for =" doc in ChatMess" :key="doc.id" class="rounded-xl bg-red-100 w-max md:w-1/3 lg:w1/3 xl:w-1/5 2xl:w-1/5">
                <p class="font-bold">{{ doc.name }}</p><br>
                <p class="text-left mx-4">{{ doc.message }}</p>
                <p class="created-at">{{ doc.createdAt.toDate() }}</p>
              </div><br><br>
            </div>
    

    This allows the displayName to be added as name everytime a message is sent.

    This ended up working best for me, thanks Alex for the help your answer works as well.


  2. How do I get just one singular field out of a Firestore document?

    There is no way you can read only one field from a document using the client SDKs. It is the entire document or nothing. There are however two ways in which you can solve this problem. You can duplicate the documents, meaning that you’ll have a document with all fields and another one that contains only a single field. Alternatively, you can use the Firestore Node.js client or Firebase Admin SDK, then you can use select() to select only
    the fields you need.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search