Implementing a dynamic navbar in Vue.js using Firebase authentication

I've been diving into a Vue.js project that allows users to sign up and log in. I've incorporated Firebase Authentication for the login and sign up functionality. Successfully, I've implemented the feature where the navbar state changes: when the user is logged out, two buttons are displayed - one for login and the other for sign up. Once the user signs in, these buttons are replaced with the user's name and the option to sign out. The issue arises with the sign up option: after submitting the form, the navbar state alters and shows the sign out option, but the username is not displayed. I want to either display the user's name along with the sign out button or prevent the application from automatically logging in after sign up. Is there a way to achieve this?

Sign up form script:

import firebase from "firebase";

export default {
  name: 'Sign-Up',
  components: {
  },
  data() {
    return {
      form: {
        errors: [],
        name: "",
        email: "",
        username: "",
        password: ""
      },
      error: null
    };
  },
  methods: {
    submit() {
      firebase
        .auth()
        .createUserWithEmailAndPassword(this.form.email, this.form.password)
        .then(data => {
          data.user
            .updateProfile({
              displayName: this.form.name
            })
            .then(() => {})
            .then(this.$router.replace({ name: "Profile" }))
        })
        .catch(err => {
          this.error = err.message;
        });
    }
  }
}

Navbar

        <template v-if="user.loggedIn">
          <ul class="nav col-12 col-md-auto mb-2 justify-content-center mb-md-0">
            <li style="margin-top: 0.5em;"><router-link to="/Dashboard" class="nav-link px-2">Hello, {{user.data.displayName}}</router-link></li>
            <li><a href="#" class="nav-link px-2" @click.prevent="signOut"><button type="button" class="btn poke-secondary me-2">Sign out</button></a></li>
          </ul>
        </template>
        <template v-else>
          <div class="col-md-3 text-end px-2">
            <router-link to="/login"><button type="button" class="btn poke-secondary me-2">Login</button></router-link>
            <router-link to="/signup"><button type="button" class="btn poke-secondary">Sign Up</button></router-link>
          </div>
        </template>

<script>
import { mapGetters } from "vuex";
import firebase from "firebase/app";
export default {
  name: "Header",
  computed: {
    ...mapGetters({
      user: "user"
    })
  },
  methods: {
    signOut() {
      firebase
        .auth()
        .signOut()
        .then(() => {
          this.$router.replace({
            name: "Home"
          });
        });
    }
  }
};
</script>

store.js:

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
  state: {
    user: {
      loggedIn: false,
      data: null
    }
  },
  getters: {
    user(state){
      return state.user
    }
  },
  mutations: {
    SET_LOGGED_IN(state, value) {
      state.user.loggedIn = value;
    },
    SET_USER(state, data) {
      state.user.data = data;
    }
  },
  actions: {
    fetchUser({ commit }, user) {
      commit("SET_LOGGED_IN", user !== null);
      if (user) {
        commit("SET_USER", {
          displayName: user.displayName,
          email: user.email
        });
      } else {
        commit("SET_USER", null);
      }
    }
  }
});

Answer №1

I am seeking a solution to either showing the user's name and sign out button, or preventing automatic login immediately after the user signs up. Is there a way to achieve this?

According to the documentation, the createUserWithEmailAndPassword() method will automatically sign in the user upon successful account creation.

It seems that there is no direct way to prevent the user from being signed in "right after signing up". The issue arises from the asynchronous nature of the updateProfile() method, which causes a slight delay in updating the displayName. To address this, you can handle the scenario by only displaying the Hello, {{user.data.displayName}} string and the "Sign Out" button when the displayName is not null.

Answer №2

According to @Renaud's explanation, the user will be automatically logged in once the createUserWithEmailAndPassword method is completed. This will only render the div if the displayName is not null, which can be achieved by using

v-if="user.data.displayName !== null"
.

Another option is to utilize a Cloud function to create new users if you want to avoid the delay in displaying the username. By creating users with the Admin SDK in the cloud function, the users will not be automatically logged in on the client side. A simple callable function for this purpose would be:

exports.createNewUser = functions.https.onCall((data, context) => {
  const {email, password, displayName} = data
  
  return admin.auth().createUser({ email, password, displayName }).then((userRecord) => {
    console.log('Successfully created new user:', userRecord.uid);
    return {data: userRecord.uid}
  }) 
});

This function will create a new user with the provided credentials and username. You can call this function from your Vue app like this:

methods: {
  submit() {
    const createUser = firebase.functions().httpsCallable('createNewUser');
    createNewUser({ 
      email: this.form.email, 
      password: this.form.password,
      displayName: this.form.name
    }).then((result) => {
      const result = result.data;

      // Manually sign in user now
      // signInWithEmailAndPassword(this.form.email, this.form.password)
    });
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to modify the inactive color of just one radio button in Framework7?

Is there a way to change the inactive color of only one radio button in Framework7? I am aware that using the CSS variable --f7-radio-inactive-color allows me to set the inactive color for all radio buttons. However, I specifically want to modify the inac ...

Implementing the Disabled Attribute on a Dynamically Generated Button Using React

My QWERTY keyboard is dynamically rendered through a component as Bootstrap buttons using bootstrap-react. Each button does not have an ID to avoid relying on IDs in React. When a letter button is clicked, it triggers an onClick event passed as props back ...

Utilize the href attribute on an image, whether it be through a class

I work as a designer and I'm looking to extract the same href link from class="kt-testimonial-title", either in id="slick-slide10", or in class="kt-testimonial-item-wrap kt-testimonial-item-0", or in class="kt-testimonial-image". Can this be achieved ...

I am facing difficulties installing packages such as react-bootstrap on my dashboard

Encountering an issue with installing packages in my dashboard. For example, attempting to install react-bootstrap results in the following error: node version: 12.16.1 npm version: 6.13.4 gyp ERR! UNCAUGHT EXCEPTION gyp ERR! stack Error: Cannot find mo ...

The iframe is set to take the source URL from url.com/id using the "id" parameter

Currently, I am attempting to set the src of an iframe by extracting the URL from the toolbar address. The URL consists of the domain plus an ID, which happens to be the same as the YouTube ID. For instance: www.youtube.com/watch=id In my case, my domain ...

"Creating a duplicate of an element by utilizing the `next`

I have a dilemma involving two divs within a section of my project - one div is dynamically created while the other exists statically. My goal is to transfer the non-dynamically created div into the one that is generated dynamically. let adContainer = $ ...

What is the best way to implement client-side shopping cart calculations using jQuery?

https://i.stack.imgur.com/aOajr.png Here is the content of my shopping cart. Below, I will explain the flow. [product image clicked] -> ajax request fetches details from database for that particular product id and appends (product name,id and price ...

The cookie being sent from the backend API (implemented in nodeJS using express) to the frontend (developed with NextJS) is not successfully setting in the

I'm currently working on a NextJS app running on localhost:3000 and a node express API running on localhost:3030. I have encountered an issue where, after sending a request from the frontend to the backend login route, I am trying to set a cookie call ...

Is there a way to get Axios to display CSS on the page?

While working on a Web Viewer project with axios for web scraping practice, I encountered an issue where the CSS wasn't loading properly. Here is the code snippet I used: console.log("Tribble-Webviewer is starting!") const express = requir ...

Retrieve markers from the database and display them as a layer that can be easily togg

I am currently working on integrating custom markers from a database into my Google map. While I have successfully loaded KML layers, I aim to allow users to save and load their personalized markers stored in the database. The structure of my database is ...

Booting up a module in AngularJS without using automatic bootstrapping

Here is the structure of my HTML... <body id="main"> {{pageName}} </body> This is how I implement it in JavaScript: angular.module('myApp',[]) .controller('myController', function($scope){ console.log('initial ...

What is the best way to run a code block every time a new reaction is added in discord.js?

I need assistance with creating a bot that can count the number of specific reactions ('⚪') to a message within a specified time frame. Additionally, I want to be able to skip the remaining time by reacting to a different emoji ('X'). ...

Delete with Express Router

I have created a basic "Grocery List" web application using the MERN stack (Mongo, Express, React, Node). However, I am facing an issue where my DELETE REST command does not execute unless I refresh the page. Here is the code for my event handler and the b ...

Protractor successfully opens Firefox, however no URL is loaded. Chrome, on the other hand, functions perfectly

Every time I attempt to execute my protractor tests on Firefox, the browser opens but no URL is loaded. Eventually, an error message appears in the command prompt: Using FirefoxDriver directly... [launcher] Running 1 instances of WebDriver ERROR - Unabl ...

The combination of Javascript and CSS allows for interactive and visually

I'm currently working on a project where I had to create a simulated weather page using only Javascript. However, I am struggling with the overall layout and have a few questions that I hope someone can help me with: Despite trying various methods ...

Navigating with Vue Router in a Nuxt JS vuex Store

In my app, I'm currently developing a login/register system using Firebase and Vuex for authentication and database management. Within Nuxt JS, I have implemented actions to create a user, log them in, and sign them out. After a successful registrati ...

What steps can I take to troubleshoot why my data isn't appearing in Vue.js?

I'm currently diving into the world of vue.js and attempting to follow this tutorial where data is being successfully displayed. https://i.sstatic.net/2RIwn.png App.vue <template> <div class="container"> <Header ...

Oops! We encountered an issue: Unhandled promise rejection. The function n.swapComponent is not defined

Currently, I am in the process of developing an application with Laravel using Jetsream and the Vuejs & Inertia stack. After executing the npm audit fix command, my entire application is displaying a blank page. The reason behind running the npm command n ...

"Is there a way to modify the color of the button once it's been clicked, but only for the specific button that was

Looking to create a Quiz App using React and facing an issue where all buttons change color when clicked, instead of just the one that was clicked. Any solutions on how to make only the clicked button change its color in React.js? App.js import Main from ...

Can a Vue.js project import the bootstrap.min.js file?

I have been working on a project in Vue.js where Bootstrap is already integrated. The project consists of HTML and CSS which I am converting into a Vue.js application while utilizing Bootstrap classes. However, I have encountered an issue with the dropdown ...